File: gso.h

package info (click to toggle)
openvswitch 2.6.2~pre%2Bgit20161223-3
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 42,772 kB
  • ctags: 37,668
  • sloc: sh: 499,654; ansic: 261,360; xml: 21,326; python: 14,843; makefile: 450; perl: 409
file content (209 lines) | stat: -rw-r--r-- 5,268 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#ifndef __LINUX_GSO_WRAPPER_H
#define __LINUX_GSO_WRAPPER_H

#include <linux/version.h>
#include "datapath.h"

typedef void (*gso_fix_segment_t)(struct sk_buff *);

struct ovs_gso_cb {
	struct ovs_skb_cb dp_cb;
#ifndef USE_UPSTREAM_TUNNEL
	struct metadata_dst	*tun_dst;
#endif
#ifndef USE_UPSTREAM_TUNNEL_GSO
	gso_fix_segment_t fix_segment;
	bool ipv6;
#endif
#ifndef HAVE_INNER_PROTOCOL
	__be16		inner_protocol;
#endif
#ifndef USE_UPSTREAM_TUNNEL
	/* Keep original tunnel info during userspace action execution. */
	struct metadata_dst *fill_md_dst;
#endif
};
#define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)->cb)


#ifndef USE_UPSTREAM_TUNNEL_GSO
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/protocol.h>

static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
{
	OVS_GSO_CB(skb)->fix_segment = NULL;
}
#else
static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
{

}
#endif

#ifndef HAVE_INNER_PROTOCOL
static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb)
{
	OVS_GSO_CB(skb)->inner_protocol = htons(0);
}

static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
					      __be16 ethertype)
{
	OVS_GSO_CB(skb)->inner_protocol = ethertype;
}

static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
{
	return OVS_GSO_CB(skb)->inner_protocol;
}

#else

static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb)
{
	/* Nothing to do. The inner_protocol is either zero or
	 * has been set to a value by another user.
	 * Either way it may be considered initialised.
	 */
}

static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
{
	return skb->inner_protocol;
}

#ifdef ENCAP_TYPE_ETHER
#define ovs_skb_set_inner_protocol skb_set_inner_protocol
#else
static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
					      __be16 ethertype)
{
	skb->inner_protocol = ethertype;
}
#endif /* ENCAP_TYPE_ETHER */
#endif /* HAVE_INNER_PROTOCOL */

#define skb_inner_mac_offset rpl_skb_inner_mac_offset
static inline int skb_inner_mac_offset(const struct sk_buff *skb)
{
	return skb_inner_mac_header(skb) - skb->data;
}

#ifndef USE_UPSTREAM_TUNNEL_GSO
#define ip_local_out rpl_ip_local_out
int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);

#define ip6_local_out rpl_ip6_local_out
int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
#else

static inline int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
#ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
	/* net and sk parameters are added at same time. */
	return ip_local_out(net, sk, skb);
#else
	return ip_local_out(skb);
#endif
}
#define ip_local_out rpl_ip_local_out

static inline int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	memset(IP6CB(skb), 0, sizeof (*IP6CB(skb)));
#ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
	return ip6_local_out(net, sk, skb);
#else
	return ip6_local_out(skb);
#endif
}
#define ip6_local_out rpl_ip6_local_out

#endif /* USE_UPSTREAM_TUNNEL_GSO */

#ifndef USE_UPSTREAM_TUNNEL
/* We need two separate functions to manage different dst in this case.
 * First is dst_entry and second is tunnel-dst.
 * So define ovs_* separate functions for tun_dst.
 */
static inline void ovs_skb_dst_set(struct sk_buff *skb, void *dst)
{
	OVS_GSO_CB(skb)->tun_dst = (void *)dst;
}

static inline struct ip_tunnel_info *ovs_skb_tunnel_info(struct sk_buff *skb)
{
	if (likely(OVS_GSO_CB(skb)->tun_dst))
		return &OVS_GSO_CB(skb)->tun_dst->u.tun_info;
	else
		return NULL;
}

static inline void ovs_skb_dst_drop(struct sk_buff *skb)
{
	OVS_GSO_CB(skb)->tun_dst = NULL;
}

static inline void ovs_dst_hold(void *dst)
{
}

static inline void ovs_dst_release(struct dst_entry *dst)
{
	struct metadata_dst *tun_dst = (struct metadata_dst *) dst;

	dst_cache_destroy(&tun_dst->u.tun_info.dst_cache);
	kfree(dst);
}

#else
#define ovs_skb_dst_set skb_dst_set
#define ovs_skb_dst_drop skb_dst_drop
#define ovs_dst_hold dst_hold
#define ovs_dst_release dst_release
#endif

#ifndef USE_UPSTREAM_TUNNEL
#define SKB_INIT_FILL_METADATA_DST(skb)	OVS_GSO_CB(skb)->fill_md_dst = NULL;

#define SKB_RESTORE_FILL_METADATA_DST(skb)	do {			\
	if (OVS_GSO_CB(skb)->fill_md_dst) {					\
		kfree(OVS_GSO_CB(skb)->tun_dst);			\
		OVS_GSO_CB(skb)->tun_dst = OVS_GSO_CB(skb)->fill_md_dst;	\
	}								\
} while (0)


#define SKB_SETUP_FILL_METADATA_DST(skb) ({			\
	struct metadata_dst *new_md_dst;			\
	struct metadata_dst *md_dst;				\
	int md_size;						\
	int ret = 1;						\
								\
	SKB_RESTORE_FILL_METADATA_DST(skb); 			\
	new_md_dst = kmalloc(sizeof(struct metadata_dst) + 256, GFP_ATOMIC); \
	if (new_md_dst) {						\
		md_dst = OVS_GSO_CB(skb)->tun_dst;			\
		md_size = new_md_dst->u.tun_info.options_len;		\
		memcpy(&new_md_dst->u.tun_info, &md_dst->u.tun_info,	\
			sizeof(struct ip_tunnel_info) + md_size);	\
									\
		OVS_GSO_CB(skb)->fill_md_dst = md_dst;				\
		OVS_GSO_CB(skb)->tun_dst = new_md_dst;			\
		ret = 1;						\
	} else {							\
		ret = 0;						\
	}								\
	ret;								\
})

#else
#define SKB_INIT_FILL_METADATA_DST(skb)		do {} while(0)
#define SKB_SETUP_FILL_METADATA_DST(skb)	(true)
#define SKB_RESTORE_FILL_METADATA_DST(skb)	do {} while(0)
#endif

#endif