1 #ifndef __LINUX_GSO_WRAPPER_H
2 #define __LINUX_GSO_WRAPPER_H
4 #include <linux/version.h>
7 typedef void (*gso_fix_segment_t)(struct sk_buff *);
10 struct ovs_skb_cb dp_cb;
11 #ifndef USE_UPSTREAM_TUNNEL
12 struct metadata_dst *tun_dst;
14 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
15 gso_fix_segment_t fix_segment;
17 #ifndef HAVE_INNER_PROTOCOL
18 __be16 inner_protocol;
20 #ifndef HAVE_NDO_FILL_METADATA_DST
21 /* Keep original tunnel info during userspace action execution. */
22 struct metadata_dst *fill_md_dst;
26 #define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)->cb)
29 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
30 #include <linux/netdevice.h>
31 #include <linux/skbuff.h>
32 #include <net/protocol.h>
34 static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
36 OVS_GSO_CB(skb)->fix_segment = NULL;
39 static inline void skb_clear_ovs_gso_cb(struct sk_buff *skb)
45 #ifndef HAVE_INNER_PROTOCOL
46 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb)
48 OVS_GSO_CB(skb)->inner_protocol = htons(0);
51 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
54 OVS_GSO_CB(skb)->inner_protocol = ethertype;
57 static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
59 return OVS_GSO_CB(skb)->inner_protocol;
64 static inline void ovs_skb_init_inner_protocol(struct sk_buff *skb)
66 /* Nothing to do. The inner_protocol is either zero or
67 * has been set to a value by another user.
68 * Either way it may be considered initialised.
72 static inline __be16 ovs_skb_get_inner_protocol(struct sk_buff *skb)
74 return skb->inner_protocol;
77 #ifdef ENCAP_TYPE_ETHER
78 #define ovs_skb_set_inner_protocol skb_set_inner_protocol
80 static inline void ovs_skb_set_inner_protocol(struct sk_buff *skb,
83 skb->inner_protocol = ethertype;
85 #endif /* ENCAP_TYPE_ETHER */
86 #endif /* HAVE_INNER_PROTOCOL */
88 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0)
89 static inline int skb_inner_mac_offset(const struct sk_buff *skb)
91 return skb_inner_mac_header(skb) - skb->data;
94 #define ip_local_out rpl_ip_local_out
95 int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
97 #define ip6_local_out rpl_ip6_local_out
98 int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb);
101 static inline int rpl_ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
103 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
104 #ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
105 /* net and sk parameters are added at same time. */
106 return ip_local_out(net, sk, skb);
108 return ip_local_out(skb);
111 #define ip_local_out rpl_ip_local_out
113 static inline int rpl_ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
115 memset(IP6CB(skb), 0, sizeof (*IP6CB(skb)));
116 #ifdef HAVE_IP_LOCAL_OUT_TAKES_NET
117 return ip6_local_out(net, sk, skb);
119 return ip6_local_out(skb);
122 #define ip6_local_out rpl_ip6_local_out
126 #ifndef USE_UPSTREAM_TUNNEL
127 /* We need two separate functions to manage different dst in this case.
128 * First is dst_entry and second is tunnel-dst.
129 * So define ovs_* separate functions for tun_dst.
131 static inline void ovs_skb_dst_set(struct sk_buff *skb, void *dst)
133 OVS_GSO_CB(skb)->tun_dst = (void *)dst;
136 static inline struct ip_tunnel_info *ovs_skb_tunnel_info(struct sk_buff *skb)
138 if (likely(OVS_GSO_CB(skb)->tun_dst))
139 return &OVS_GSO_CB(skb)->tun_dst->u.tun_info;
144 static inline void ovs_skb_dst_drop(struct sk_buff *skb)
146 OVS_GSO_CB(skb)->tun_dst = NULL;
149 static inline void ovs_dst_hold(void *dst)
153 static inline void ovs_dst_release(struct dst_entry *dst)
155 struct metadata_dst *tun_dst = (struct metadata_dst *) dst;
157 dst_cache_destroy(&tun_dst->u.tun_info.dst_cache);
162 #define ovs_skb_dst_set skb_dst_set
163 #define ovs_skb_dst_drop skb_dst_drop
164 #define ovs_dst_hold dst_hold
165 #define ovs_dst_release dst_release
168 #ifndef HAVE_NDO_FILL_METADATA_DST
169 #define SKB_INIT_FILL_METADATA_DST(skb) OVS_GSO_CB(skb)->fill_md_dst = NULL;
171 #define SKB_RESTORE_FILL_METADATA_DST(skb) do { \
172 if (OVS_GSO_CB(skb)->fill_md_dst) { \
173 kfree(OVS_GSO_CB(skb)->tun_dst); \
174 OVS_GSO_CB(skb)->tun_dst = OVS_GSO_CB(skb)->fill_md_dst; \
179 #define SKB_SETUP_FILL_METADATA_DST(skb) ({ \
180 struct metadata_dst *new_md_dst; \
181 struct metadata_dst *md_dst; \
185 SKB_RESTORE_FILL_METADATA_DST(skb); \
186 new_md_dst = kmalloc(sizeof(struct metadata_dst) + 256, GFP_ATOMIC); \
188 md_dst = OVS_GSO_CB(skb)->tun_dst; \
189 md_size = new_md_dst->u.tun_info.options_len; \
190 memcpy(&new_md_dst->u.tun_info, &md_dst->u.tun_info, \
191 sizeof(struct ip_tunnel_info) + md_size); \
193 OVS_GSO_CB(skb)->fill_md_dst = md_dst; \
194 OVS_GSO_CB(skb)->tun_dst = new_md_dst; \
203 #define SKB_INIT_FILL_METADATA_DST(skb) do {} while(0)
204 #define SKB_SETUP_FILL_METADATA_DST(skb) (true)
205 #define SKB_RESTORE_FILL_METADATA_DST(skb) do {} while(0)