Blame view
net/openvswitch/flow.c
23.9 KB
c94229992 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
ccb1352e7 net: Add Open vSw... |
2 |
/* |
971427f35 openvswitch: Add ... |
3 |
* Copyright (c) 2007-2014 Nicira, Inc. |
ccb1352e7 net: Add Open vSw... |
4 |
*/ |
ccb1352e7 net: Add Open vSw... |
5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <linux/uaccess.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <net/llc_pdu.h> #include <linux/kernel.h> #include <linux/jhash.h> #include <linux/jiffies.h> #include <linux/llc.h> #include <linux/module.h> #include <linux/in.h> #include <linux/rcupdate.h> |
db74a3335 openvswitch: use ... |
18 |
#include <linux/cpumask.h> |
ccb1352e7 net: Add Open vSw... |
19 |
#include <linux/if_arp.h> |
ccb1352e7 net: Add Open vSw... |
20 21 |
#include <linux/ip.h> #include <linux/ipv6.h> |
25cd9ba0a openvswitch: Add ... |
22 |
#include <linux/mpls.h> |
a175a7233 openvswitch: Add ... |
23 |
#include <linux/sctp.h> |
e298e5057 openvswitch: Per ... |
24 |
#include <linux/smp.h> |
ccb1352e7 net: Add Open vSw... |
25 26 27 28 29 30 |
#include <linux/tcp.h> #include <linux/udp.h> #include <linux/icmp.h> #include <linux/icmpv6.h> #include <linux/rculist.h> #include <net/ip.h> |
7d5437c70 openvswitch: Add ... |
31 |
#include <net/ip_tunnels.h> |
ccb1352e7 net: Add Open vSw... |
32 |
#include <net/ipv6.h> |
25cd9ba0a openvswitch: Add ... |
33 |
#include <net/mpls.h> |
ccb1352e7 net: Add Open vSw... |
34 |
#include <net/ndisc.h> |
b2d0f5d5d openvswitch: enab... |
35 |
#include <net/nsh.h> |
ccb1352e7 net: Add Open vSw... |
36 |
|
a581b96db openvswitch: Remo... |
37 |
#include "conntrack.h" |
83c8df26a openvswitch: refa... |
38 39 40 |
#include "datapath.h" #include "flow.h" #include "flow_netlink.h" |
a581b96db openvswitch: Remo... |
41 |
#include "vport.h" |
83c8df26a openvswitch: refa... |
42 |
|
e64457191 openvswitch: Rest... |
43 |
u64 ovs_flow_used_time(unsigned long flow_jiffies) |
03f0d916a openvswitch: Mega... |
44 |
{ |
311af51dc openvswitch: use ... |
45 |
struct timespec64 cur_ts; |
e64457191 openvswitch: Rest... |
46 |
u64 cur_ms, idle_ms; |
03f0d916a openvswitch: Mega... |
47 |
|
311af51dc openvswitch: use ... |
48 |
ktime_get_ts64(&cur_ts); |
e64457191 openvswitch: Rest... |
49 |
idle_ms = jiffies_to_msecs(jiffies - flow_jiffies); |
311af51dc openvswitch: use ... |
50 |
cur_ms = (u64)(u32)cur_ts.tv_sec * MSEC_PER_SEC + |
e64457191 openvswitch: Rest... |
51 |
cur_ts.tv_nsec / NSEC_PER_MSEC; |
03f0d916a openvswitch: Mega... |
52 |
|
e64457191 openvswitch: Rest... |
53 |
return cur_ms - idle_ms; |
5828cd9a6 openvswitch: opti... |
54 |
} |
df23e9f64 openvswitch: Wide... |
55 |
#define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF)) |
03f0d916a openvswitch: Mega... |
56 |
|
ad5520073 openvswitch: Fix ... |
57 |
void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, |
12eb18f71 openvswitch: Cons... |
58 |
const struct sk_buff *skb) |
03f0d916a openvswitch: Mega... |
59 |
{ |
aef833c58 net: openvswitch:... |
60 |
struct sw_flow_stats *stats; |
c4b2bf6b4 openvswitch: Opti... |
61 |
unsigned int cpu = smp_processor_id(); |
df8a39def net: rename vlan_... |
62 |
int len = skb->len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); |
03f0d916a openvswitch: Mega... |
63 |
|
db74a3335 openvswitch: use ... |
64 |
stats = rcu_dereference(flow->stats[cpu]); |
e298e5057 openvswitch: Per ... |
65 |
|
db74a3335 openvswitch: use ... |
66 |
/* Check if already have CPU-specific stats. */ |
63e7959c4 openvswitch: Per ... |
67 68 69 |
if (likely(stats)) { spin_lock(&stats->lock); /* Mark if we write on the pre-allocated stats. */ |
db74a3335 openvswitch: use ... |
70 71 |
if (cpu == 0 && unlikely(flow->stats_last_writer != cpu)) flow->stats_last_writer = cpu; |
63e7959c4 openvswitch: Per ... |
72 73 74 |
} else { stats = rcu_dereference(flow->stats[0]); /* Pre-allocated. */ spin_lock(&stats->lock); |
db74a3335 openvswitch: use ... |
75 |
/* If the current CPU is the only writer on the |
63e7959c4 openvswitch: Per ... |
76 77 |
* pre-allocated stats keep using them. */ |
db74a3335 openvswitch: use ... |
78 |
if (unlikely(flow->stats_last_writer != cpu)) { |
63e7959c4 openvswitch: Per ... |
79 |
/* A previous locker may have already allocated the |
db74a3335 openvswitch: use ... |
80 |
* stats, so we need to check again. If CPU-specific |
63e7959c4 openvswitch: Per ... |
81 82 83 |
* stats were already allocated, we update the pre- * allocated stats as we have already locked them. */ |
db74a3335 openvswitch: use ... |
84 85 86 |
if (likely(flow->stats_last_writer != -1) && likely(!rcu_access_pointer(flow->stats[cpu]))) { /* Try to allocate CPU-specific stats. */ |
aef833c58 net: openvswitch:... |
87 |
struct sw_flow_stats *new_stats; |
63e7959c4 openvswitch: Per ... |
88 89 90 |
new_stats = kmem_cache_alloc_node(flow_stats_cache, |
4167e9b2c mm: remove GFP_TH... |
91 92 93 |
GFP_NOWAIT | __GFP_THISNODE | __GFP_NOWARN | |
63e7959c4 openvswitch: Per ... |
94 |
__GFP_NOMEMALLOC, |
c57c054eb openvswitch: Opti... |
95 |
numa_node_id()); |
63e7959c4 openvswitch: Per ... |
96 97 98 |
if (likely(new_stats)) { new_stats->used = jiffies; new_stats->packet_count = 1; |
24cc59d1e openvswitch: Cons... |
99 |
new_stats->byte_count = len; |
63e7959c4 openvswitch: Per ... |
100 101 |
new_stats->tcp_flags = tcp_flags; spin_lock_init(&new_stats->lock); |
db74a3335 openvswitch: use ... |
102 |
rcu_assign_pointer(flow->stats[cpu], |
63e7959c4 openvswitch: Per ... |
103 |
new_stats); |
c4b2bf6b4 openvswitch: Opti... |
104 |
cpumask_set_cpu(cpu, &flow->cpu_used_mask); |
63e7959c4 openvswitch: Per ... |
105 106 107 |
goto unlock; } } |
db74a3335 openvswitch: use ... |
108 |
flow->stats_last_writer = cpu; |
63e7959c4 openvswitch: Per ... |
109 110 |
} } |
e298e5057 openvswitch: Per ... |
111 112 |
stats->used = jiffies; stats->packet_count++; |
24cc59d1e openvswitch: Cons... |
113 |
stats->byte_count += len; |
e298e5057 openvswitch: Per ... |
114 |
stats->tcp_flags |= tcp_flags; |
63e7959c4 openvswitch: Per ... |
115 |
unlock: |
e298e5057 openvswitch: Per ... |
116 117 |
spin_unlock(&stats->lock); } |
86ec8dbae openvswitch: Fix ... |
118 119 120 |
/* Must be called with rcu_read_lock or ovs_mutex. */ void ovs_flow_stats_get(const struct sw_flow *flow, struct ovs_flow_stats *ovs_stats, |
e298e5057 openvswitch: Per ... |
121 122 |
unsigned long *used, __be16 *tcp_flags) { |
db74a3335 openvswitch: use ... |
123 |
int cpu; |
e298e5057 openvswitch: Per ... |
124 125 126 127 |
*used = 0; *tcp_flags = 0; memset(ovs_stats, 0, sizeof(*ovs_stats)); |
db74a3335 openvswitch: use ... |
128 |
/* We open code this to make sure cpu 0 is always considered */ |
c4b2bf6b4 openvswitch: Opti... |
129 |
for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) { |
aef833c58 net: openvswitch:... |
130 |
struct sw_flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]); |
63e7959c4 openvswitch: Per ... |
131 132 133 134 135 136 137 138 139 140 141 142 143 |
if (stats) { /* Local CPU may write on non-local stats, so we must * block bottom-halves here. */ spin_lock_bh(&stats->lock); if (!*used || time_after(stats->used, *used)) *used = stats->used; *tcp_flags |= stats->tcp_flags; ovs_stats->n_packets += stats->packet_count; ovs_stats->n_bytes += stats->byte_count; spin_unlock_bh(&stats->lock); } |
e298e5057 openvswitch: Per ... |
144 |
} |
e298e5057 openvswitch: Per ... |
145 |
} |
86ec8dbae openvswitch: Fix ... |
146 |
/* Called with ovs_mutex. */ |
e298e5057 openvswitch: Per ... |
147 148 |
void ovs_flow_stats_clear(struct sw_flow *flow) { |
db74a3335 openvswitch: use ... |
149 |
int cpu; |
63e7959c4 openvswitch: Per ... |
150 |
|
db74a3335 openvswitch: use ... |
151 |
/* We open code this to make sure cpu 0 is always considered */ |
c4b2bf6b4 openvswitch: Opti... |
152 |
for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) { |
aef833c58 net: openvswitch:... |
153 |
struct sw_flow_stats *stats = ovsl_dereference(flow->stats[cpu]); |
63e7959c4 openvswitch: Per ... |
154 155 156 157 158 159 160 161 162 163 |
if (stats) { spin_lock_bh(&stats->lock); stats->used = 0; stats->packet_count = 0; stats->byte_count = 0; stats->tcp_flags = 0; spin_unlock_bh(&stats->lock); } } |
03f0d916a openvswitch: Mega... |
164 |
} |
ccb1352e7 net: Add Open vSw... |
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 210 211 212 213 214 215 216 217 218 219 |
static int check_header(struct sk_buff *skb, int len) { if (unlikely(skb->len < len)) return -EINVAL; if (unlikely(!pskb_may_pull(skb, len))) return -ENOMEM; return 0; } static bool arphdr_ok(struct sk_buff *skb) { return pskb_may_pull(skb, skb_network_offset(skb) + sizeof(struct arp_eth_header)); } static int check_iphdr(struct sk_buff *skb) { unsigned int nh_ofs = skb_network_offset(skb); unsigned int ip_len; int err; err = check_header(skb, nh_ofs + sizeof(struct iphdr)); if (unlikely(err)) return err; ip_len = ip_hdrlen(skb); if (unlikely(ip_len < sizeof(struct iphdr) || skb->len < nh_ofs + ip_len)) return -EINVAL; skb_set_transport_header(skb, nh_ofs + ip_len); return 0; } static bool tcphdr_ok(struct sk_buff *skb) { int th_ofs = skb_transport_offset(skb); int tcp_len; if (unlikely(!pskb_may_pull(skb, th_ofs + sizeof(struct tcphdr)))) return false; tcp_len = tcp_hdrlen(skb); if (unlikely(tcp_len < sizeof(struct tcphdr) || skb->len < th_ofs + tcp_len)) return false; return true; } static bool udphdr_ok(struct sk_buff *skb) { return pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)); } |
a175a7233 openvswitch: Add ... |
220 221 222 223 224 |
static bool sctphdr_ok(struct sk_buff *skb) { return pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct sctphdr)); } |
ccb1352e7 net: Add Open vSw... |
225 226 227 228 229 |
static bool icmphdr_ok(struct sk_buff *skb) { return pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct icmphdr)); } |
03f0d916a openvswitch: Mega... |
230 |
static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key) |
ccb1352e7 net: Add Open vSw... |
231 |
{ |
fa642f088 openvswitch: Deri... |
232 233 |
unsigned short frag_off; unsigned int payload_ofs = 0; |
ccb1352e7 net: Add Open vSw... |
234 235 |
unsigned int nh_ofs = skb_network_offset(skb); unsigned int nh_len; |
ccb1352e7 net: Add Open vSw... |
236 |
struct ipv6hdr *nh; |
fa642f088 openvswitch: Deri... |
237 |
int err, nexthdr, flags = 0; |
ccb1352e7 net: Add Open vSw... |
238 |
|
ccb1352e7 net: Add Open vSw... |
239 240 241 242 243 |
err = check_header(skb, nh_ofs + sizeof(*nh)); if (unlikely(err)) return err; nh = ipv6_hdr(skb); |
ccb1352e7 net: Add Open vSw... |
244 245 246 247 248 249 250 |
key->ip.proto = NEXTHDR_NONE; key->ip.tos = ipv6_get_dsfield(nh); key->ip.ttl = nh->hop_limit; key->ipv6.label = *(__be32 *)nh & htonl(IPV6_FLOWINFO_FLOWLABEL); key->ipv6.addr.src = nh->saddr; key->ipv6.addr.dst = nh->daddr; |
fa642f088 openvswitch: Deri... |
251 252 |
nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags); if (flags & IP6_FH_F_FRAG) { |
41e4e2cd7 openvswitch: Fix ... |
253 |
if (frag_off) { |
ccb1352e7 net: Add Open vSw... |
254 |
key->ip.frag = OVS_FRAG_TYPE_LATER; |
41e4e2cd7 openvswitch: Fix ... |
255 256 257 258 |
key->ip.proto = nexthdr; return 0; } key->ip.frag = OVS_FRAG_TYPE_FIRST; |
25ef1328a openvswitch: Set ... |
259 260 |
} else { key->ip.frag = OVS_FRAG_TYPE_NONE; |
ccb1352e7 net: Add Open vSw... |
261 |
} |
fa642f088 openvswitch: Deri... |
262 263 |
/* Delayed handling of error in ipv6_find_hdr() as it * always sets flags and frag_off to a valid value which may be |
c30da4978 openvswitch: reta... |
264 265 |
* used to set key->ip.frag above. */ |
fa642f088 openvswitch: Deri... |
266 |
if (unlikely(nexthdr < 0)) |
c30da4978 openvswitch: reta... |
267 |
return -EPROTO; |
ccb1352e7 net: Add Open vSw... |
268 269 270 271 272 273 274 275 276 277 278 |
nh_len = payload_ofs - nh_ofs; skb_set_transport_header(skb, nh_ofs + nh_len); key->ip.proto = nexthdr; return nh_len; } static bool icmp6hdr_ok(struct sk_buff *skb) { return pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct icmp6hdr)); } |
018c1dda5 openvswitch: 802.... |
279 280 281 282 283 284 |
/** * Parse vlan tag from vlan header. * Returns ERROR on memory error. * Returns 0 if it encounters a non-vlan or incomplete packet. * Returns 1 after successfully parsing vlan tag. */ |
df30f7408 openvswitch: upca... |
285 286 |
static int parse_vlan_tag(struct sk_buff *skb, struct vlan_head *key_vh, bool untag_vlan) |
ccb1352e7 net: Add Open vSw... |
287 |
{ |
018c1dda5 openvswitch: 802.... |
288 |
struct vlan_head *vh = (struct vlan_head *)skb->data; |
ccb1352e7 net: Add Open vSw... |
289 |
|
018c1dda5 openvswitch: 802.... |
290 |
if (likely(!eth_type_vlan(vh->tpid))) |
ccb1352e7 net: Add Open vSw... |
291 |
return 0; |
018c1dda5 openvswitch: 802.... |
292 293 294 295 296 |
if (unlikely(skb->len < sizeof(struct vlan_head) + sizeof(__be16))) return 0; if (unlikely(!pskb_may_pull(skb, sizeof(struct vlan_head) + sizeof(__be16)))) |
ccb1352e7 net: Add Open vSw... |
297 |
return -ENOMEM; |
018c1dda5 openvswitch: 802.... |
298 |
vh = (struct vlan_head *)skb->data; |
9df46aefa OVS: remove use o... |
299 |
key_vh->tci = vh->tci | htons(VLAN_CFI_MASK); |
018c1dda5 openvswitch: 802.... |
300 |
key_vh->tpid = vh->tpid; |
df30f7408 openvswitch: upca... |
301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
if (unlikely(untag_vlan)) { int offset = skb->data - skb_mac_header(skb); u16 tci; int err; __skb_push(skb, offset); err = __skb_vlan_pop(skb, &tci); __skb_pull(skb, offset); if (err) return err; __vlan_hwaccel_put_tag(skb, key_vh->tpid, tci); } else { __skb_pull(skb, sizeof(struct vlan_head)); } |
018c1dda5 openvswitch: 802.... |
315 316 |
return 1; } |
5108bbadd openvswitch: add ... |
317 |
static void clear_vlan(struct sw_flow_key *key) |
018c1dda5 openvswitch: 802.... |
318 |
{ |
018c1dda5 openvswitch: 802.... |
319 320 321 322 |
key->eth.vlan.tci = 0; key->eth.vlan.tpid = 0; key->eth.cvlan.tci = 0; key->eth.cvlan.tpid = 0; |
5108bbadd openvswitch: add ... |
323 324 325 326 327 |
} static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key) { int res; |
018c1dda5 openvswitch: 802.... |
328 |
|
20ecf1e4e openvswitch: vlan... |
329 |
if (skb_vlan_tag_present(skb)) { |
9df46aefa OVS: remove use o... |
330 |
key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK); |
018c1dda5 openvswitch: 802.... |
331 332 333 |
key->eth.vlan.tpid = skb->vlan_proto; } else { /* Parse outer vlan tag in the non-accelerated case. */ |
df30f7408 openvswitch: upca... |
334 |
res = parse_vlan_tag(skb, &key->eth.vlan, true); |
018c1dda5 openvswitch: 802.... |
335 336 337 338 339 |
if (res <= 0) return res; } /* Parse inner vlan tag. */ |
df30f7408 openvswitch: upca... |
340 |
res = parse_vlan_tag(skb, &key->eth.cvlan, false); |
018c1dda5 openvswitch: 802.... |
341 342 |
if (res <= 0) return res; |
ccb1352e7 net: Add Open vSw... |
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 |
return 0; } static __be16 parse_ethertype(struct sk_buff *skb) { struct llc_snap_hdr { u8 dsap; /* Always 0xAA */ u8 ssap; /* Always 0xAA */ u8 ctrl; u8 oui[3]; __be16 ethertype; }; struct llc_snap_hdr *llc; __be16 proto; proto = *(__be16 *) skb->data; __skb_pull(skb, sizeof(__be16)); |
6713fc9b8 openvswitch: Use ... |
361 |
if (eth_proto_is_802_3(proto)) |
ccb1352e7 net: Add Open vSw... |
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
return proto; if (skb->len < sizeof(struct llc_snap_hdr)) return htons(ETH_P_802_2); if (unlikely(!pskb_may_pull(skb, sizeof(struct llc_snap_hdr)))) return htons(0); llc = (struct llc_snap_hdr *) skb->data; if (llc->dsap != LLC_SAP_SNAP || llc->ssap != LLC_SAP_SNAP || (llc->oui[0] | llc->oui[1] | llc->oui[2]) != 0) return htons(ETH_P_802_2); __skb_pull(skb, sizeof(struct llc_snap_hdr)); |
17b682a04 openvswitch: Fix ... |
377 |
|
6713fc9b8 openvswitch: Use ... |
378 |
if (eth_proto_is_802_3(llc->ethertype)) |
17b682a04 openvswitch: Fix ... |
379 380 381 |
return llc->ethertype; return htons(ETH_P_802_2); |
ccb1352e7 net: Add Open vSw... |
382 383 384 |
} static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, |
03f0d916a openvswitch: Mega... |
385 |
int nh_len) |
ccb1352e7 net: Add Open vSw... |
386 387 |
{ struct icmp6hdr *icmp = icmp6_hdr(skb); |
ccb1352e7 net: Add Open vSw... |
388 389 390 391 |
/* The ICMPv6 type and code fields use the 16-bit transport port * fields, so we need to store them in 16-bit network byte order. */ |
1139e241e openvswitch: Comp... |
392 393 |
key->tp.src = htons(icmp->icmp6_type); key->tp.dst = htons(icmp->icmp6_code); |
25ef1328a openvswitch: Set ... |
394 |
memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd)); |
ccb1352e7 net: Add Open vSw... |
395 396 397 398 399 400 401 |
if (icmp->icmp6_code == 0 && (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION || icmp->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT)) { int icmp_len = skb->len - skb_transport_offset(skb); struct nd_msg *nd; int offset; |
ccb1352e7 net: Add Open vSw... |
402 403 404 405 |
/* In order to process neighbor discovery options, we need the * entire packet. */ if (unlikely(icmp_len < sizeof(*nd))) |
03f0d916a openvswitch: Mega... |
406 407 408 409 |
return 0; if (unlikely(skb_linearize(skb))) return -ENOMEM; |
ccb1352e7 net: Add Open vSw... |
410 411 412 |
nd = (struct nd_msg *)skb_transport_header(skb); key->ipv6.nd.target = nd->target; |
ccb1352e7 net: Add Open vSw... |
413 414 415 416 417 418 419 420 421 |
icmp_len -= sizeof(*nd); offset = 0; while (icmp_len >= 8) { struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd->opt + offset); int opt_len = nd_opt->nd_opt_len * 8; if (unlikely(!opt_len || opt_len > icmp_len)) |
03f0d916a openvswitch: Mega... |
422 |
return 0; |
ccb1352e7 net: Add Open vSw... |
423 424 425 426 427 428 429 430 431 |
/* Store the link layer address if the appropriate * option is provided. It is considered an error if * the same link layer option is specified twice. */ if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR && opt_len == 8) { if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll))) goto invalid; |
8c63ff09b openvswitch: Use ... |
432 433 |
ether_addr_copy(key->ipv6.nd.sll, &nd->opt[offset+sizeof(*nd_opt)]); |
ccb1352e7 net: Add Open vSw... |
434 435 436 437 |
} else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR && opt_len == 8) { if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll))) goto invalid; |
8c63ff09b openvswitch: Use ... |
438 439 |
ether_addr_copy(key->ipv6.nd.tll, &nd->opt[offset+sizeof(*nd_opt)]); |
ccb1352e7 net: Add Open vSw... |
440 441 442 443 444 445 |
} icmp_len -= opt_len; offset += opt_len; } } |
03f0d916a openvswitch: Mega... |
446 |
return 0; |
ccb1352e7 net: Add Open vSw... |
447 448 449 450 451 |
invalid: memset(&key->ipv6.nd.target, 0, sizeof(key->ipv6.nd.target)); memset(key->ipv6.nd.sll, 0, sizeof(key->ipv6.nd.sll)); memset(key->ipv6.nd.tll, 0, sizeof(key->ipv6.nd.tll)); |
03f0d916a openvswitch: Mega... |
452 |
return 0; |
ccb1352e7 net: Add Open vSw... |
453 |
} |
b2d0f5d5d openvswitch: enab... |
454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 |
static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key) { struct nshhdr *nh; unsigned int nh_ofs = skb_network_offset(skb); u8 version, length; int err; err = check_header(skb, nh_ofs + NSH_BASE_HDR_LEN); if (unlikely(err)) return err; nh = nsh_hdr(skb); version = nsh_get_ver(nh); length = nsh_hdr_len(nh); if (version != 0) return -EINVAL; err = check_header(skb, nh_ofs + length); if (unlikely(err)) return err; nh = nsh_hdr(skb); key->nsh.base.flags = nsh_get_flags(nh); key->nsh.base.ttl = nsh_get_ttl(nh); key->nsh.base.mdtype = nh->mdtype; key->nsh.base.np = nh->np; key->nsh.base.path_hdr = nh->path_hdr; switch (key->nsh.base.mdtype) { case NSH_M_TYPE1: if (length != NSH_M_TYPE1_LEN) return -EINVAL; memcpy(key->nsh.context, nh->md1.context, sizeof(nh->md1)); break; case NSH_M_TYPE2: memset(key->nsh.context, 0, sizeof(nh->md1)); break; default: return -EINVAL; } return 0; } |
ccb1352e7 net: Add Open vSw... |
499 |
/** |
ad06a566e openvswitch: Prop... |
500 |
* key_extract_l3l4 - extracts L3/L4 header information. |
ccb1352e7 net: Add Open vSw... |
501 |
* @skb: sk_buff that contains the frame, with skb->data pointing to the |
ad06a566e openvswitch: Prop... |
502 |
* L3 header |
ccb1352e7 net: Add Open vSw... |
503 |
* @key: output flow key |
ccb1352e7 net: Add Open vSw... |
504 |
* |
ccb1352e7 net: Add Open vSw... |
505 |
*/ |
ad06a566e openvswitch: Prop... |
506 |
static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key) |
ccb1352e7 net: Add Open vSw... |
507 |
{ |
03f0d916a openvswitch: Mega... |
508 |
int error; |
ccb1352e7 net: Add Open vSw... |
509 510 511 512 513 |
/* Network layer. */ if (key->eth.type == htons(ETH_P_IP)) { struct iphdr *nh; __be16 offset; |
ccb1352e7 net: Add Open vSw... |
514 515 |
error = check_iphdr(skb); if (unlikely(error)) { |
071481213 openvswitch: Elim... |
516 517 |
memset(&key->ip, 0, sizeof(key->ip)); memset(&key->ipv4, 0, sizeof(key->ipv4)); |
ccb1352e7 net: Add Open vSw... |
518 519 520 521 |
if (error == -EINVAL) { skb->transport_header = skb->network_header; error = 0; } |
03f0d916a openvswitch: Mega... |
522 |
return error; |
ccb1352e7 net: Add Open vSw... |
523 524 525 526 527 528 529 530 531 532 533 534 535 |
} nh = ip_hdr(skb); key->ipv4.addr.src = nh->saddr; key->ipv4.addr.dst = nh->daddr; key->ip.proto = nh->protocol; key->ip.tos = nh->tos; key->ip.ttl = nh->ttl; offset = nh->frag_off & htons(IP_OFFSET); if (offset) { key->ip.frag = OVS_FRAG_TYPE_LATER; |
0754b4e8c openvswitch: Clea... |
536 |
memset(&key->tp, 0, sizeof(key->tp)); |
03f0d916a openvswitch: Mega... |
537 |
return 0; |
ccb1352e7 net: Add Open vSw... |
538 |
} |
0c19f846d net: accept UFO d... |
539 540 |
if (nh->frag_off & htons(IP_MF) || skb_shinfo(skb)->gso_type & SKB_GSO_UDP) |
ccb1352e7 net: Add Open vSw... |
541 |
key->ip.frag = OVS_FRAG_TYPE_FIRST; |
071481213 openvswitch: Elim... |
542 543 |
else key->ip.frag = OVS_FRAG_TYPE_NONE; |
ccb1352e7 net: Add Open vSw... |
544 545 546 |
/* Transport layer. */ if (key->ip.proto == IPPROTO_TCP) { |
ccb1352e7 net: Add Open vSw... |
547 548 |
if (tcphdr_ok(skb)) { struct tcphdr *tcp = tcp_hdr(skb); |
1139e241e openvswitch: Comp... |
549 550 551 |
key->tp.src = tcp->source; key->tp.dst = tcp->dest; key->tp.flags = TCP_FLAGS_BE16(tcp); |
071481213 openvswitch: Elim... |
552 553 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
ccb1352e7 net: Add Open vSw... |
554 |
} |
071481213 openvswitch: Elim... |
555 |
|
ccb1352e7 net: Add Open vSw... |
556 |
} else if (key->ip.proto == IPPROTO_UDP) { |
ccb1352e7 net: Add Open vSw... |
557 558 |
if (udphdr_ok(skb)) { struct udphdr *udp = udp_hdr(skb); |
1139e241e openvswitch: Comp... |
559 560 |
key->tp.src = udp->source; key->tp.dst = udp->dest; |
071481213 openvswitch: Elim... |
561 562 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
ccb1352e7 net: Add Open vSw... |
563 |
} |
a175a7233 openvswitch: Add ... |
564 565 566 |
} else if (key->ip.proto == IPPROTO_SCTP) { if (sctphdr_ok(skb)) { struct sctphdr *sctp = sctp_hdr(skb); |
1139e241e openvswitch: Comp... |
567 568 |
key->tp.src = sctp->source; key->tp.dst = sctp->dest; |
071481213 openvswitch: Elim... |
569 570 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
a175a7233 openvswitch: Add ... |
571 |
} |
ccb1352e7 net: Add Open vSw... |
572 |
} else if (key->ip.proto == IPPROTO_ICMP) { |
ccb1352e7 net: Add Open vSw... |
573 574 575 576 577 |
if (icmphdr_ok(skb)) { struct icmphdr *icmp = icmp_hdr(skb); /* The ICMP type and code fields use the 16-bit * transport port fields, so we need to store * them in 16-bit network byte order. */ |
1139e241e openvswitch: Comp... |
578 579 |
key->tp.src = htons(icmp->type); key->tp.dst = htons(icmp->code); |
071481213 openvswitch: Elim... |
580 581 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
ccb1352e7 net: Add Open vSw... |
582 583 |
} } |
071481213 openvswitch: Elim... |
584 585 |
} else if (key->eth.type == htons(ETH_P_ARP) || key->eth.type == htons(ETH_P_RARP)) { |
ccb1352e7 net: Add Open vSw... |
586 |
struct arp_eth_header *arp; |
389f48947 openvswitch: fix ... |
587 |
bool arp_available = arphdr_ok(skb); |
ccb1352e7 net: Add Open vSw... |
588 589 |
arp = (struct arp_eth_header *)skb_network_header(skb); |
389f48947 openvswitch: fix ... |
590 |
if (arp_available && |
071481213 openvswitch: Elim... |
591 592 593 594 |
arp->ar_hrd == htons(ARPHRD_ETHER) && arp->ar_pro == htons(ETH_P_IP) && arp->ar_hln == ETH_ALEN && arp->ar_pln == 4) { |
ccb1352e7 net: Add Open vSw... |
595 596 597 598 |
/* We only match on the lower 8 bits of the opcode. */ if (ntohs(arp->ar_op) <= 0xff) key->ip.proto = ntohs(arp->ar_op); |
071481213 openvswitch: Elim... |
599 600 |
else key->ip.proto = 0; |
d04d38298 openvswitch: Stor... |
601 602 |
memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src)); memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst)); |
8c63ff09b openvswitch: Use ... |
603 604 |
ether_addr_copy(key->ipv4.arp.sha, arp->ar_sha); ether_addr_copy(key->ipv4.arp.tha, arp->ar_tha); |
071481213 openvswitch: Elim... |
605 606 607 |
} else { memset(&key->ip, 0, sizeof(key->ip)); memset(&key->ipv4, 0, sizeof(key->ipv4)); |
ccb1352e7 net: Add Open vSw... |
608 |
} |
25cd9ba0a openvswitch: Add ... |
609 |
} else if (eth_p_mpls(key->eth.type)) { |
fbdcdd78d Change in Openvsw... |
610 |
u8 label_count = 1; |
25cd9ba0a openvswitch: Add ... |
611 |
|
fbdcdd78d Change in Openvsw... |
612 |
memset(&key->mpls, 0, sizeof(key->mpls)); |
f7d49bce8 openvswitch: mpls... |
613 |
skb_set_inner_network_header(skb, skb->mac_len); |
25cd9ba0a openvswitch: Add ... |
614 615 |
while (1) { __be32 lse; |
fbdcdd78d Change in Openvsw... |
616 617 |
error = check_header(skb, skb->mac_len + label_count * MPLS_HLEN); |
25cd9ba0a openvswitch: Add ... |
618 619 |
if (unlikely(error)) return 0; |
f7d49bce8 openvswitch: mpls... |
620 |
memcpy(&lse, skb_inner_network_header(skb), MPLS_HLEN); |
25cd9ba0a openvswitch: Add ... |
621 |
|
fbdcdd78d Change in Openvsw... |
622 623 624 |
if (label_count <= MPLS_LABEL_DEPTH) memcpy(&key->mpls.lse[label_count - 1], &lse, MPLS_HLEN); |
25cd9ba0a openvswitch: Add ... |
625 |
|
fbdcdd78d Change in Openvsw... |
626 627 |
skb_set_inner_network_header(skb, skb->mac_len + label_count * MPLS_HLEN); |
25cd9ba0a openvswitch: Add ... |
628 629 |
if (lse & htonl(MPLS_LS_S_MASK)) break; |
fbdcdd78d Change in Openvsw... |
630 |
label_count++; |
25cd9ba0a openvswitch: Add ... |
631 |
} |
fbdcdd78d Change in Openvsw... |
632 633 634 635 |
if (label_count > MPLS_LABEL_DEPTH) label_count = MPLS_LABEL_DEPTH; key->mpls.num_labels_mask = GENMASK(label_count - 1, 0); |
ccb1352e7 net: Add Open vSw... |
636 637 |
} else if (key->eth.type == htons(ETH_P_IPV6)) { int nh_len; /* IPv6 Header + Extensions */ |
03f0d916a openvswitch: Mega... |
638 |
nh_len = parse_ipv6hdr(skb, key); |
ccb1352e7 net: Add Open vSw... |
639 |
if (unlikely(nh_len < 0)) { |
c30da4978 openvswitch: reta... |
640 641 642 643 |
switch (nh_len) { case -EINVAL: memset(&key->ip, 0, sizeof(key->ip)); memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr)); |
df561f668 treewide: Use fal... |
644 |
fallthrough; |
c30da4978 openvswitch: reta... |
645 |
case -EPROTO: |
ccb1352e7 net: Add Open vSw... |
646 |
skb->transport_header = skb->network_header; |
03f0d916a openvswitch: Mega... |
647 |
error = 0; |
c30da4978 openvswitch: reta... |
648 649 |
break; default: |
ccb1352e7 net: Add Open vSw... |
650 |
error = nh_len; |
03f0d916a openvswitch: Mega... |
651 652 |
} return error; |
ccb1352e7 net: Add Open vSw... |
653 |
} |
0754b4e8c openvswitch: Clea... |
654 655 |
if (key->ip.frag == OVS_FRAG_TYPE_LATER) { memset(&key->tp, 0, sizeof(key->tp)); |
03f0d916a openvswitch: Mega... |
656 |
return 0; |
0754b4e8c openvswitch: Clea... |
657 |
} |
0c19f846d net: accept UFO d... |
658 659 |
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) key->ip.frag = OVS_FRAG_TYPE_FIRST; |
ccb1352e7 net: Add Open vSw... |
660 661 |
/* Transport layer. */ if (key->ip.proto == NEXTHDR_TCP) { |
ccb1352e7 net: Add Open vSw... |
662 663 |
if (tcphdr_ok(skb)) { struct tcphdr *tcp = tcp_hdr(skb); |
1139e241e openvswitch: Comp... |
664 665 666 |
key->tp.src = tcp->source; key->tp.dst = tcp->dest; key->tp.flags = TCP_FLAGS_BE16(tcp); |
071481213 openvswitch: Elim... |
667 668 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
ccb1352e7 net: Add Open vSw... |
669 670 |
} } else if (key->ip.proto == NEXTHDR_UDP) { |
ccb1352e7 net: Add Open vSw... |
671 672 |
if (udphdr_ok(skb)) { struct udphdr *udp = udp_hdr(skb); |
1139e241e openvswitch: Comp... |
673 674 |
key->tp.src = udp->source; key->tp.dst = udp->dest; |
071481213 openvswitch: Elim... |
675 676 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
ccb1352e7 net: Add Open vSw... |
677 |
} |
a175a7233 openvswitch: Add ... |
678 679 680 |
} else if (key->ip.proto == NEXTHDR_SCTP) { if (sctphdr_ok(skb)) { struct sctphdr *sctp = sctp_hdr(skb); |
1139e241e openvswitch: Comp... |
681 682 |
key->tp.src = sctp->source; key->tp.dst = sctp->dest; |
071481213 openvswitch: Elim... |
683 684 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
a175a7233 openvswitch: Add ... |
685 |
} |
ccb1352e7 net: Add Open vSw... |
686 |
} else if (key->ip.proto == NEXTHDR_ICMP) { |
ccb1352e7 net: Add Open vSw... |
687 |
if (icmp6hdr_ok(skb)) { |
03f0d916a openvswitch: Mega... |
688 689 690 |
error = parse_icmpv6(skb, key, nh_len); if (error) return error; |
071481213 openvswitch: Elim... |
691 692 |
} else { memset(&key->tp, 0, sizeof(key->tp)); |
ccb1352e7 net: Add Open vSw... |
693 694 |
} } |
b2d0f5d5d openvswitch: enab... |
695 696 697 698 |
} else if (key->eth.type == htons(ETH_P_NSH)) { error = parse_nsh(skb, key); if (error) return error; |
ccb1352e7 net: Add Open vSw... |
699 |
} |
03f0d916a openvswitch: Mega... |
700 |
return 0; |
ccb1352e7 net: Add Open vSw... |
701 |
} |
83c8df26a openvswitch: refa... |
702 |
|
ad06a566e openvswitch: Prop... |
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
/** * key_extract - extracts a flow key from an Ethernet frame. * @skb: sk_buff that contains the frame, with skb->data pointing to the * Ethernet header * @key: output flow key * * The caller must ensure that skb->len >= ETH_HLEN. * * Returns 0 if successful, otherwise a negative errno value. * * Initializes @skb header fields as follows: * * - skb->mac_header: the L2 header. * * - skb->network_header: just past the L2 header, or just past the * VLAN header, to the first byte of the L2 payload. * * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 * on output, then just past the IP header, if one is present and * of a correct length, otherwise the same as skb->network_header. * For other key->eth.type values it is left untouched. * * - skb->protocol: the type of the data starting at skb->network_header. * Equals to key->eth.type. */ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) { struct ethhdr *eth; /* Flags are always used as part of stats */ key->tp.flags = 0; skb_reset_mac_header(skb); /* Link layer. */ clear_vlan(key); if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { if (unlikely(eth_type_vlan(skb->protocol))) return -EINVAL; skb_reset_network_header(skb); key->eth.type = skb->protocol; } else { eth = eth_hdr(skb); ether_addr_copy(key->eth.src, eth->h_source); ether_addr_copy(key->eth.dst, eth->h_dest); __skb_pull(skb, 2 * ETH_ALEN); /* We are going to push all headers that we pull, so no need to * update skb->csum here. */ if (unlikely(parse_vlan(skb, key))) return -ENOMEM; key->eth.type = parse_ethertype(skb); if (unlikely(key->eth.type == htons(0))) return -ENOMEM; /* Multiple tagged packets need to retain TPID to satisfy * skb_vlan_pop(), which will later shift the ethertype into * skb->protocol. */ if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK)) skb->protocol = key->eth.cvlan.tpid; else skb->protocol = key->eth.type; skb_reset_network_header(skb); __skb_push(skb, skb->data - skb_mac_header(skb)); } skb_reset_mac_len(skb); /* Fill out L3/L4 key info, if any */ return key_extract_l3l4(skb, key); } /* In the case of conntrack fragment handling it expects L3 headers, * add a helper. */ int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key) { return key_extract_l3l4(skb, key); } |
971427f35 openvswitch: Add ... |
788 789 |
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key) { |
6f56f6186 openvswitch: Fix ... |
790 791 792 793 794 795 796 |
int res; res = key_extract(skb, key); if (!res) key->mac_proto &= ~SW_FLOW_KEY_INVALID; return res; |
971427f35 openvswitch: Add ... |
797 |
} |
5108bbadd openvswitch: add ... |
798 799 800 801 802 803 804 805 806 807 808 809 810 |
static int key_extract_mac_proto(struct sk_buff *skb) { switch (skb->dev->type) { case ARPHRD_ETHER: return MAC_PROTO_ETHERNET; case ARPHRD_NONE: if (skb->protocol == htons(ETH_P_TEB)) return MAC_PROTO_ETHERNET; return MAC_PROTO_NONE; } WARN_ON_ONCE(1); return -EINVAL; } |
1d8fff907 ip_tunnel: Make o... |
811 |
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, |
8c8b1b83f openvswitch: Use ... |
812 |
struct sk_buff *skb, struct sw_flow_key *key) |
83c8df26a openvswitch: refa... |
813 |
{ |
95a7233c4 net: openvswitch:... |
814 815 816 |
#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) struct tc_skb_ext *tc_ext; #endif |
9dd7f8907 openvswitch: Add ... |
817 |
int res, err; |
5108bbadd openvswitch: add ... |
818 |
|
83c8df26a openvswitch: refa... |
819 |
/* Extract metadata from packet. */ |
f57966840 openvswitch: Add ... |
820 |
if (tun_info) { |
00a93babd openvswitch: add ... |
821 |
key->tun_proto = ip_tunnel_info_af(tun_info); |
1d8fff907 ip_tunnel: Make o... |
822 |
memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key)); |
f57966840 openvswitch: Add ... |
823 |
|
4c2227984 ip-tunnel: Use AP... |
824 |
if (tun_info->options_len) { |
f57966840 openvswitch: Add ... |
825 826 827 |
BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) * 8)) - 1 > sizeof(key->tun_opts)); |
4c2227984 ip-tunnel: Use AP... |
828 829 830 |
ip_tunnel_info_opts_get(TUN_METADATA_OPTS(key, tun_info->options_len), tun_info); |
f57966840 openvswitch: Add ... |
831 832 833 834 835 |
key->tun_opts_len = tun_info->options_len; } else { key->tun_opts_len = 0; } } else { |
00a93babd openvswitch: add ... |
836 |
key->tun_proto = 0; |
f57966840 openvswitch: Add ... |
837 |
key->tun_opts_len = 0; |
071481213 openvswitch: Elim... |
838 |
memset(&key->tun_key, 0, sizeof(key->tun_key)); |
f57966840 openvswitch: Add ... |
839 |
} |
83c8df26a openvswitch: refa... |
840 841 842 843 |
key->phy.priority = skb->priority; key->phy.in_port = OVS_CB(skb)->input_vport->port_no; key->phy.skb_mark = skb->mark; |
071481213 openvswitch: Elim... |
844 |
key->ovs_flow_hash = 0; |
5108bbadd openvswitch: add ... |
845 846 847 848 |
res = key_extract_mac_proto(skb); if (res < 0) return res; key->mac_proto = res; |
95a7233c4 net: openvswitch:... |
849 850 851 852 853 |
#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) if (static_branch_unlikely(&tc_recirc_sharing_support)) { tc_ext = skb_ext_find(skb, TC_SKB_EXT); key->recirc_id = tc_ext ? tc_ext->chain : 0; |
038ebb1a7 net/sched: act_ct... |
854 |
OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0; |
95a7233c4 net: openvswitch:... |
855 856 857 858 |
} else { key->recirc_id = 0; } #else |
071481213 openvswitch: Elim... |
859 |
key->recirc_id = 0; |
95a7233c4 net: openvswitch:... |
860 |
#endif |
071481213 openvswitch: Elim... |
861 |
|
9dd7f8907 openvswitch: Add ... |
862 863 864 865 |
err = key_extract(skb, key); if (!err) ovs_ct_fill_key(skb, key); /* Must be after key_extract(). */ return err; |
83c8df26a openvswitch: refa... |
866 |
} |
c2ac66735 openvswitch: Allo... |
867 |
int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr, |
83c8df26a openvswitch: refa... |
868 |
struct sk_buff *skb, |
05da5898a openvswitch: Add ... |
869 |
struct sw_flow_key *key, bool log) |
83c8df26a openvswitch: refa... |
870 |
{ |
9dd7f8907 openvswitch: Add ... |
871 872 |
const struct nlattr *a[OVS_KEY_ATTR_MAX + 1]; u64 attrs = 0; |
83c8df26a openvswitch: refa... |
873 |
int err; |
9dd7f8907 openvswitch: Add ... |
874 875 876 |
err = parse_flow_nlattrs(attr, a, &attrs, log); if (err) return -EINVAL; |
83c8df26a openvswitch: refa... |
877 |
/* Extract metadata from netlink attributes. */ |
9dd7f8907 openvswitch: Add ... |
878 |
err = ovs_nla_get_flow_metadata(net, a, attrs, key, log); |
83c8df26a openvswitch: refa... |
879 880 |
if (err) return err; |
df30f7408 openvswitch: upca... |
881 882 883 884 885 886 887 888 |
/* key_extract assumes that skb->protocol is set-up for * layer 3 packets which is the case for other callers, * in particular packets received from the network stack. * Here the correct value can be set from the metadata * extracted above. * For L2 packet key eth type would be zero. skb protocol * would be set to correct value later during key-extact. */ |
5108bbadd openvswitch: add ... |
889 |
|
df30f7408 openvswitch: upca... |
890 |
skb->protocol = key->eth.type; |
9dd7f8907 openvswitch: Add ... |
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 |
err = key_extract(skb, key); if (err) return err; /* Check that we have conntrack original direction tuple metadata only * for packets for which it makes sense. Otherwise the key may be * corrupted due to overlapping key fields. */ if (attrs & (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4) && key->eth.type != htons(ETH_P_IP)) return -EINVAL; if (attrs & (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6) && (key->eth.type != htons(ETH_P_IPV6) || sw_flow_key_is_nd(key))) return -EINVAL; return 0; |
83c8df26a openvswitch: refa... |
908 |
} |