From 6e0ce48e27d5a845bdc8b57fb41bcec8a54f336a Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Thu, 30 Dec 2010 20:48:38 -0800 Subject: [PATCH] datapath: Add vlan acceleration field for older kernels. Kernels prior to 2.6.27 did not have a vlan_tci field in struct sk_buff for vlan acceleration. It's very convenient to use this field for manipulating vlan tags, so we would like to use it as the primary mechanism. To enable this, this commit adds similar infrastructure to the OVS_CB on the kernels that need it and a set of functions to use the correct location. Signed-off-by: Jesse Gross Acked-by: Ben Pfaff --- datapath/Modules.mk | 2 ++ datapath/datapath.h | 6 +++++ datapath/vlan.c | 48 +++++++++++++++++++++++++++++++++++ datapath/vlan.h | 46 +++++++++++++++++++++++++++++++++ datapath/vport-internal_dev.c | 2 ++ datapath/vport-netdev.c | 2 ++ 6 files changed, 106 insertions(+) create mode 100644 datapath/vlan.c create mode 100644 datapath/vlan.h diff --git a/datapath/Modules.mk b/datapath/Modules.mk index c4afae20..dbeec8fb 100644 --- a/datapath/Modules.mk +++ b/datapath/Modules.mk @@ -20,6 +20,7 @@ openvswitch_sources = \ loop_counter.c \ table.c \ tunnel.c \ + vlan.c \ vport.c \ vport-capwap.c \ vport-generic.c \ @@ -37,6 +38,7 @@ openvswitch_headers = \ loop_counter.h \ table.h \ tunnel.h \ + vlan.h \ vport.h \ vport-generic.h \ vport-internal_dev.h \ diff --git a/datapath/datapath.h b/datapath/datapath.h index befa55cb..a7795105 100644 --- a/datapath/datapath.h +++ b/datapath/datapath.h @@ -22,6 +22,7 @@ #include "checksum.h" #include "flow.h" #include "dp_sysfs.h" +#include "vlan.h" struct vport; @@ -104,6 +105,8 @@ struct datapath { * kernel versions. * @tun_id: ID of the tunnel that encapsulated this packet. It is 0 if the * packet was not received on a tunnel. + * @vlan_tci: Provides a substitute for the skb->vlan_tci field on kernels + * before 2.6.27. */ struct ovs_skb_cb { struct vport *vport; @@ -112,6 +115,9 @@ struct ovs_skb_cb { enum csum_type ip_summed; #endif __be64 tun_id; +#ifdef NEED_VLAN_FIELD + u16 vlan_tci; +#endif }; #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) diff --git a/datapath/vlan.c b/datapath/vlan.c new file mode 100644 index 00000000..9aebecd0 --- /dev/null +++ b/datapath/vlan.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2011 Nicira Networks. + * Distributed under the terms of the GNU GPL version 2. + * + * Significant portions of this file may be copied from parts of the Linux + * kernel, by Linus Torvalds and others. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include + +#include "datapath.h" +#include "vlan.h" + +#ifdef NEED_VLAN_FIELD +void vlan_copy_skb_tci(struct sk_buff *skb) +{ + OVS_CB(skb)->vlan_tci = 0; +} + +u16 vlan_get_tci(struct sk_buff *skb) +{ + return OVS_CB(skb)->vlan_tci; +} + +void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci) +{ + OVS_CB(skb)->vlan_tci = vlan_tci; +} + +bool vlan_tx_tag_present(struct sk_buff *skb) +{ + return OVS_CB(skb)->vlan_tci & VLAN_TAG_PRESENT; +} + +u16 vlan_tx_tag_get(struct sk_buff *skb) +{ + return OVS_CB(skb)->vlan_tci & ~VLAN_TAG_PRESENT; +} + +struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci) +{ + OVS_CB(skb)->vlan_tci = vlan_tci | VLAN_TAG_PRESENT; + return skb; +} +#endif /* NEED_VLAN_FIELD */ diff --git a/datapath/vlan.h b/datapath/vlan.h new file mode 100644 index 00000000..dc900183 --- /dev/null +++ b/datapath/vlan.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Nicira Networks. + * Distributed under the terms of the GNU GPL version 2. + * + * Significant portions of this file may be copied from parts of the Linux + * kernel, by Linus Torvalds and others. + */ + +#ifndef VLAN_H +#define VLAN_H 1 + +#include +#include +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) +#define NEED_VLAN_FIELD +#endif + +#ifndef NEED_VLAN_FIELD +static inline void vlan_copy_skb_tci(struct sk_buff *skb) { } + +static inline u16 vlan_get_tci(struct sk_buff *skb) +{ + return skb->vlan_tci; +} + +static inline void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci) +{ + skb->vlan_tci = vlan_tci; +} +#else +void vlan_copy_skb_tci(struct sk_buff *skb); +u16 vlan_get_tci(struct sk_buff *skb); +void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci); + +#undef vlan_tx_tag_present +bool vlan_tx_tag_present(struct sk_buff *skb); + +#undef vlan_tx_tag_get +u16 vlan_tx_tag_get(struct sk_buff *skb); + +#define __vlan_hwaccel_put_tag rpl__vlan_hwaccel_put_tag +struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci); +#endif /* NEED_VLAN_FIELD */ +#endif /* vlan.h */ diff --git a/datapath/vport-internal_dev.c b/datapath/vport-internal_dev.c index 1df61801..be290745 100644 --- a/datapath/vport-internal_dev.c +++ b/datapath/vport-internal_dev.c @@ -15,6 +15,7 @@ #include "checksum.h" #include "datapath.h" +#include "vlan.h" #include "vport-generic.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -72,6 +73,7 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p) static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) { compute_ip_summed(skb, true); + vlan_copy_skb_tci(skb); OVS_CB(skb)->flow = NULL; vport_receive(internal_dev_priv(netdev)->vport, skb); diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c index e45e22fb..85e0eb9a 100644 --- a/datapath/vport-netdev.c +++ b/datapath/vport-netdev.c @@ -18,6 +18,7 @@ #include "checksum.h" #include "datapath.h" +#include "vlan.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -252,6 +253,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb) skb_push(skb, ETH_HLEN); compute_ip_summed(skb, false); + vlan_copy_skb_tci(skb); vport_receive(vport, skb); } -- 2.30.2