Skip to content

Commit 6e0ce48

Browse files
committed
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 <jesse@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
1 parent a992ec0 commit 6e0ce48

6 files changed

Lines changed: 106 additions & 0 deletions

File tree

datapath/Modules.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ openvswitch_sources = \
2020
loop_counter.c \
2121
table.c \
2222
tunnel.c \
23+
vlan.c \
2324
vport.c \
2425
vport-capwap.c \
2526
vport-generic.c \
@@ -37,6 +38,7 @@ openvswitch_headers = \
3738
loop_counter.h \
3839
table.h \
3940
tunnel.h \
41+
vlan.h \
4042
vport.h \
4143
vport-generic.h \
4244
vport-internal_dev.h \

datapath/datapath.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "checksum.h"
2323
#include "flow.h"
2424
#include "dp_sysfs.h"
25+
#include "vlan.h"
2526

2627
struct vport;
2728

@@ -104,6 +105,8 @@ struct datapath {
104105
* kernel versions.
105106
* @tun_id: ID of the tunnel that encapsulated this packet. It is 0 if the
106107
* packet was not received on a tunnel.
108+
* @vlan_tci: Provides a substitute for the skb->vlan_tci field on kernels
109+
* before 2.6.27.
107110
*/
108111
struct ovs_skb_cb {
109112
struct vport *vport;
@@ -112,6 +115,9 @@ struct ovs_skb_cb {
112115
enum csum_type ip_summed;
113116
#endif
114117
__be64 tun_id;
118+
#ifdef NEED_VLAN_FIELD
119+
u16 vlan_tci;
120+
#endif
115121
};
116122
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
117123

datapath/vlan.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2011 Nicira Networks.
3+
* Distributed under the terms of the GNU GPL version 2.
4+
*
5+
* Significant portions of this file may be copied from parts of the Linux
6+
* kernel, by Linus Torvalds and others.
7+
*/
8+
9+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10+
11+
#include <linux/if_vlan.h>
12+
#include <linux/skbuff.h>
13+
14+
#include "datapath.h"
15+
#include "vlan.h"
16+
17+
#ifdef NEED_VLAN_FIELD
18+
void vlan_copy_skb_tci(struct sk_buff *skb)
19+
{
20+
OVS_CB(skb)->vlan_tci = 0;
21+
}
22+
23+
u16 vlan_get_tci(struct sk_buff *skb)
24+
{
25+
return OVS_CB(skb)->vlan_tci;
26+
}
27+
28+
void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci)
29+
{
30+
OVS_CB(skb)->vlan_tci = vlan_tci;
31+
}
32+
33+
bool vlan_tx_tag_present(struct sk_buff *skb)
34+
{
35+
return OVS_CB(skb)->vlan_tci & VLAN_TAG_PRESENT;
36+
}
37+
38+
u16 vlan_tx_tag_get(struct sk_buff *skb)
39+
{
40+
return OVS_CB(skb)->vlan_tci & ~VLAN_TAG_PRESENT;
41+
}
42+
43+
struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci)
44+
{
45+
OVS_CB(skb)->vlan_tci = vlan_tci | VLAN_TAG_PRESENT;
46+
return skb;
47+
}
48+
#endif /* NEED_VLAN_FIELD */

datapath/vlan.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright (c) 2011 Nicira Networks.
3+
* Distributed under the terms of the GNU GPL version 2.
4+
*
5+
* Significant portions of this file may be copied from parts of the Linux
6+
* kernel, by Linus Torvalds and others.
7+
*/
8+
9+
#ifndef VLAN_H
10+
#define VLAN_H 1
11+
12+
#include <linux/if_vlan.h>
13+
#include <linux/skbuff.h>
14+
#include <linux/version.h>
15+
16+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
17+
#define NEED_VLAN_FIELD
18+
#endif
19+
20+
#ifndef NEED_VLAN_FIELD
21+
static inline void vlan_copy_skb_tci(struct sk_buff *skb) { }
22+
23+
static inline u16 vlan_get_tci(struct sk_buff *skb)
24+
{
25+
return skb->vlan_tci;
26+
}
27+
28+
static inline void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci)
29+
{
30+
skb->vlan_tci = vlan_tci;
31+
}
32+
#else
33+
void vlan_copy_skb_tci(struct sk_buff *skb);
34+
u16 vlan_get_tci(struct sk_buff *skb);
35+
void vlan_set_tci(struct sk_buff *skb, u16 vlan_tci);
36+
37+
#undef vlan_tx_tag_present
38+
bool vlan_tx_tag_present(struct sk_buff *skb);
39+
40+
#undef vlan_tx_tag_get
41+
u16 vlan_tx_tag_get(struct sk_buff *skb);
42+
43+
#define __vlan_hwaccel_put_tag rpl__vlan_hwaccel_put_tag
44+
struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, u16 vlan_tci);
45+
#endif /* NEED_VLAN_FIELD */
46+
#endif /* vlan.h */

datapath/vport-internal_dev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "checksum.h"
1717
#include "datapath.h"
18+
#include "vlan.h"
1819
#include "vport-generic.h"
1920
#include "vport-internal_dev.h"
2021
#include "vport-netdev.h"
@@ -72,6 +73,7 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p)
7273
static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
7374
{
7475
compute_ip_summed(skb, true);
76+
vlan_copy_skb_tci(skb);
7577
OVS_CB(skb)->flow = NULL;
7678

7779
vport_receive(internal_dev_priv(netdev)->vport, skb);

datapath/vport-netdev.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "checksum.h"
2020
#include "datapath.h"
21+
#include "vlan.h"
2122
#include "vport-internal_dev.h"
2223
#include "vport-netdev.h"
2324

@@ -252,6 +253,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
252253

253254
skb_push(skb, ETH_HLEN);
254255
compute_ip_summed(skb, false);
256+
vlan_copy_skb_tci(skb);
255257

256258
vport_receive(vport, skb);
257259
}

0 commit comments

Comments
 (0)