diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 10:28:19 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 10:28:19 -0500 |
commit | 734d1ece37fbf3d2ddfc71bc6c69e0fe35f02542 (patch) | |
tree | c4805dd7e746b1feb9e09e9849f3245d0b2c0c6b /net/openvswitch | |
parent | 216c82c6aba63eeb49d7654b448e0d47bea255bb (diff) | |
parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) |
Merge tag 'v3.8-rc3' into v4l_for_linus
Linux 3.8-rc3
* tag 'v3.8-rc3': (11110 commits)
Linux 3.8-rc3
mm: reinstante dropped pmd_trans_splitting() check
cred: Remove tgcred pointer from struct cred
drm/ttm: fix fence locking in ttm_buffer_object_transfer
ARM: clps711x: Fix bad merge of clockevents setup
ARM: highbank: save and restore L2 cache and GIC on suspend
ARM: highbank: add a power request clear
ARM: highbank: fix secondary boot and hotplug
ARM: highbank: fix typos with hignbank in power request functions
ARM: dts: fix highbank cpu mpidr values
ARM: dts: add device_type prop to cpu nodes on Calxeda platforms
drm/prime: drop reference on imported dma-buf come from gem
xen/netfront: improve truesize tracking
ARM: mx5: Fix MX53 flexcan2 clock
ARM: OMAP2+: am33xx-hwmod: Fix wrongly terminated am33xx_usbss_mpu_irqs array
sctp: fix Kconfig bug in default cookie hmac selection
EDAC: Cleanup device deregistering path
EDAC: Fix EDAC Kconfig menu
EDAC: Fix kernel panic on module unloading
ALSA: hda - add mute LED for HP Pavilion 17 (Realtek codec)
...
Diffstat (limited to 'net/openvswitch')
-rw-r--r-- | net/openvswitch/actions.c | 97 | ||||
-rw-r--r-- | net/openvswitch/datapath.c | 27 | ||||
-rw-r--r-- | net/openvswitch/flow.c | 28 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 8 | ||||
-rw-r--r-- | net/openvswitch/vport-netdev.c | 14 | ||||
-rw-r--r-- | net/openvswitch/vport-netdev.h | 3 | ||||
-rw-r--r-- | net/openvswitch/vport.c | 5 |
7 files changed, 166 insertions, 16 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 08114478cb85..ac2defeeba83 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/if_arp.h> | 28 | #include <linux/if_arp.h> |
29 | #include <linux/if_vlan.h> | 29 | #include <linux/if_vlan.h> |
30 | #include <net/ip.h> | 30 | #include <net/ip.h> |
31 | #include <net/ipv6.h> | ||
31 | #include <net/checksum.h> | 32 | #include <net/checksum.h> |
32 | #include <net/dsfield.h> | 33 | #include <net/dsfield.h> |
33 | 34 | ||
@@ -162,6 +163,53 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh, | |||
162 | *addr = new_addr; | 163 | *addr = new_addr; |
163 | } | 164 | } |
164 | 165 | ||
166 | static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto, | ||
167 | __be32 addr[4], const __be32 new_addr[4]) | ||
168 | { | ||
169 | int transport_len = skb->len - skb_transport_offset(skb); | ||
170 | |||
171 | if (l4_proto == IPPROTO_TCP) { | ||
172 | if (likely(transport_len >= sizeof(struct tcphdr))) | ||
173 | inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb, | ||
174 | addr, new_addr, 1); | ||
175 | } else if (l4_proto == IPPROTO_UDP) { | ||
176 | if (likely(transport_len >= sizeof(struct udphdr))) { | ||
177 | struct udphdr *uh = udp_hdr(skb); | ||
178 | |||
179 | if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) { | ||
180 | inet_proto_csum_replace16(&uh->check, skb, | ||
181 | addr, new_addr, 1); | ||
182 | if (!uh->check) | ||
183 | uh->check = CSUM_MANGLED_0; | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto, | ||
190 | __be32 addr[4], const __be32 new_addr[4], | ||
191 | bool recalculate_csum) | ||
192 | { | ||
193 | if (recalculate_csum) | ||
194 | update_ipv6_checksum(skb, l4_proto, addr, new_addr); | ||
195 | |||
196 | skb->rxhash = 0; | ||
197 | memcpy(addr, new_addr, sizeof(__be32[4])); | ||
198 | } | ||
199 | |||
200 | static void set_ipv6_tc(struct ipv6hdr *nh, u8 tc) | ||
201 | { | ||
202 | nh->priority = tc >> 4; | ||
203 | nh->flow_lbl[0] = (nh->flow_lbl[0] & 0x0F) | ((tc & 0x0F) << 4); | ||
204 | } | ||
205 | |||
206 | static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl) | ||
207 | { | ||
208 | nh->flow_lbl[0] = (nh->flow_lbl[0] & 0xF0) | (fl & 0x000F0000) >> 16; | ||
209 | nh->flow_lbl[1] = (fl & 0x0000FF00) >> 8; | ||
210 | nh->flow_lbl[2] = fl & 0x000000FF; | ||
211 | } | ||
212 | |||
165 | static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl) | 213 | static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl) |
166 | { | 214 | { |
167 | csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8)); | 215 | csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8)); |
@@ -195,6 +243,47 @@ static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *ipv4_key) | |||
195 | return 0; | 243 | return 0; |
196 | } | 244 | } |
197 | 245 | ||
246 | static int set_ipv6(struct sk_buff *skb, const struct ovs_key_ipv6 *ipv6_key) | ||
247 | { | ||
248 | struct ipv6hdr *nh; | ||
249 | int err; | ||
250 | __be32 *saddr; | ||
251 | __be32 *daddr; | ||
252 | |||
253 | err = make_writable(skb, skb_network_offset(skb) + | ||
254 | sizeof(struct ipv6hdr)); | ||
255 | if (unlikely(err)) | ||
256 | return err; | ||
257 | |||
258 | nh = ipv6_hdr(skb); | ||
259 | saddr = (__be32 *)&nh->saddr; | ||
260 | daddr = (__be32 *)&nh->daddr; | ||
261 | |||
262 | if (memcmp(ipv6_key->ipv6_src, saddr, sizeof(ipv6_key->ipv6_src))) | ||
263 | set_ipv6_addr(skb, ipv6_key->ipv6_proto, saddr, | ||
264 | ipv6_key->ipv6_src, true); | ||
265 | |||
266 | if (memcmp(ipv6_key->ipv6_dst, daddr, sizeof(ipv6_key->ipv6_dst))) { | ||
267 | unsigned int offset = 0; | ||
268 | int flags = IP6_FH_F_SKIP_RH; | ||
269 | bool recalc_csum = true; | ||
270 | |||
271 | if (ipv6_ext_hdr(nh->nexthdr)) | ||
272 | recalc_csum = ipv6_find_hdr(skb, &offset, | ||
273 | NEXTHDR_ROUTING, NULL, | ||
274 | &flags) != NEXTHDR_ROUTING; | ||
275 | |||
276 | set_ipv6_addr(skb, ipv6_key->ipv6_proto, daddr, | ||
277 | ipv6_key->ipv6_dst, recalc_csum); | ||
278 | } | ||
279 | |||
280 | set_ipv6_tc(nh, ipv6_key->ipv6_tclass); | ||
281 | set_ipv6_fl(nh, ntohl(ipv6_key->ipv6_label)); | ||
282 | nh->hop_limit = ipv6_key->ipv6_hlimit; | ||
283 | |||
284 | return 0; | ||
285 | } | ||
286 | |||
198 | /* Must follow make_writable() since that can move the skb data. */ | 287 | /* Must follow make_writable() since that can move the skb data. */ |
199 | static void set_tp_port(struct sk_buff *skb, __be16 *port, | 288 | static void set_tp_port(struct sk_buff *skb, __be16 *port, |
200 | __be16 new_port, __sum16 *check) | 289 | __be16 new_port, __sum16 *check) |
@@ -339,6 +428,10 @@ static int execute_set_action(struct sk_buff *skb, | |||
339 | skb->priority = nla_get_u32(nested_attr); | 428 | skb->priority = nla_get_u32(nested_attr); |
340 | break; | 429 | break; |
341 | 430 | ||
431 | case OVS_KEY_ATTR_SKB_MARK: | ||
432 | skb->mark = nla_get_u32(nested_attr); | ||
433 | break; | ||
434 | |||
342 | case OVS_KEY_ATTR_ETHERNET: | 435 | case OVS_KEY_ATTR_ETHERNET: |
343 | err = set_eth_addr(skb, nla_data(nested_attr)); | 436 | err = set_eth_addr(skb, nla_data(nested_attr)); |
344 | break; | 437 | break; |
@@ -347,6 +440,10 @@ static int execute_set_action(struct sk_buff *skb, | |||
347 | err = set_ipv4(skb, nla_data(nested_attr)); | 440 | err = set_ipv4(skb, nla_data(nested_attr)); |
348 | break; | 441 | break; |
349 | 442 | ||
443 | case OVS_KEY_ATTR_IPV6: | ||
444 | err = set_ipv6(skb, nla_data(nested_attr)); | ||
445 | break; | ||
446 | |||
350 | case OVS_KEY_ATTR_TCP: | 447 | case OVS_KEY_ATTR_TCP: |
351 | err = set_tcp(skb, nla_data(nested_attr)); | 448 | err = set_tcp(skb, nla_data(nested_attr)); |
352 | break; | 449 | break; |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 4c4b62ccc7d7..f996db343247 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -208,7 +208,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) | |||
208 | int error; | 208 | int error; |
209 | int key_len; | 209 | int key_len; |
210 | 210 | ||
211 | stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id()); | 211 | stats = this_cpu_ptr(dp->stats_percpu); |
212 | 212 | ||
213 | /* Extract flow from 'skb' into 'key'. */ | 213 | /* Extract flow from 'skb' into 'key'. */ |
214 | error = ovs_flow_extract(skb, p->port_no, &key, &key_len); | 214 | error = ovs_flow_extract(skb, p->port_no, &key, &key_len); |
@@ -282,7 +282,7 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, | |||
282 | return 0; | 282 | return 0; |
283 | 283 | ||
284 | err: | 284 | err: |
285 | stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id()); | 285 | stats = this_cpu_ptr(dp->stats_percpu); |
286 | 286 | ||
287 | u64_stats_update_begin(&stats->sync); | 287 | u64_stats_update_begin(&stats->sync); |
288 | stats->n_lost++; | 288 | stats->n_lost++; |
@@ -479,8 +479,10 @@ static int validate_set(const struct nlattr *a, | |||
479 | 479 | ||
480 | switch (key_type) { | 480 | switch (key_type) { |
481 | const struct ovs_key_ipv4 *ipv4_key; | 481 | const struct ovs_key_ipv4 *ipv4_key; |
482 | const struct ovs_key_ipv6 *ipv6_key; | ||
482 | 483 | ||
483 | case OVS_KEY_ATTR_PRIORITY: | 484 | case OVS_KEY_ATTR_PRIORITY: |
485 | case OVS_KEY_ATTR_SKB_MARK: | ||
484 | case OVS_KEY_ATTR_ETHERNET: | 486 | case OVS_KEY_ATTR_ETHERNET: |
485 | break; | 487 | break; |
486 | 488 | ||
@@ -500,6 +502,25 @@ static int validate_set(const struct nlattr *a, | |||
500 | 502 | ||
501 | break; | 503 | break; |
502 | 504 | ||
505 | case OVS_KEY_ATTR_IPV6: | ||
506 | if (flow_key->eth.type != htons(ETH_P_IPV6)) | ||
507 | return -EINVAL; | ||
508 | |||
509 | if (!flow_key->ip.proto) | ||
510 | return -EINVAL; | ||
511 | |||
512 | ipv6_key = nla_data(ovs_key); | ||
513 | if (ipv6_key->ipv6_proto != flow_key->ip.proto) | ||
514 | return -EINVAL; | ||
515 | |||
516 | if (ipv6_key->ipv6_frag != flow_key->ip.frag) | ||
517 | return -EINVAL; | ||
518 | |||
519 | if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000) | ||
520 | return -EINVAL; | ||
521 | |||
522 | break; | ||
523 | |||
503 | case OVS_KEY_ATTR_TCP: | 524 | case OVS_KEY_ATTR_TCP: |
504 | if (flow_key->ip.proto != IPPROTO_TCP) | 525 | if (flow_key->ip.proto != IPPROTO_TCP) |
505 | return -EINVAL; | 526 | return -EINVAL; |
@@ -675,6 +696,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
675 | goto err_flow_free; | 696 | goto err_flow_free; |
676 | 697 | ||
677 | err = ovs_flow_metadata_from_nlattrs(&flow->key.phy.priority, | 698 | err = ovs_flow_metadata_from_nlattrs(&flow->key.phy.priority, |
699 | &flow->key.phy.skb_mark, | ||
678 | &flow->key.phy.in_port, | 700 | &flow->key.phy.in_port, |
679 | a[OVS_PACKET_ATTR_KEY]); | 701 | a[OVS_PACKET_ATTR_KEY]); |
680 | if (err) | 702 | if (err) |
@@ -694,6 +716,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
694 | 716 | ||
695 | OVS_CB(packet)->flow = flow; | 717 | OVS_CB(packet)->flow = flow; |
696 | packet->priority = flow->key.phy.priority; | 718 | packet->priority = flow->key.phy.priority; |
719 | packet->mark = flow->key.phy.skb_mark; | ||
697 | 720 | ||
698 | rcu_read_lock(); | 721 | rcu_read_lock(); |
699 | dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); | 722 | dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 733cbf49ed1f..c3294cebc4f2 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -604,6 +604,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, | |||
604 | 604 | ||
605 | key->phy.priority = skb->priority; | 605 | key->phy.priority = skb->priority; |
606 | key->phy.in_port = in_port; | 606 | key->phy.in_port = in_port; |
607 | key->phy.skb_mark = skb->mark; | ||
607 | 608 | ||
608 | skb_reset_mac_header(skb); | 609 | skb_reset_mac_header(skb); |
609 | 610 | ||
@@ -689,7 +690,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, | |||
689 | } | 690 | } |
690 | } | 691 | } |
691 | 692 | ||
692 | } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) { | 693 | } else if ((key->eth.type == htons(ETH_P_ARP) || |
694 | key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) { | ||
693 | struct arp_eth_header *arp; | 695 | struct arp_eth_header *arp; |
694 | 696 | ||
695 | arp = (struct arp_eth_header *)skb_network_header(skb); | 697 | arp = (struct arp_eth_header *)skb_network_header(skb); |
@@ -802,6 +804,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { | |||
802 | [OVS_KEY_ATTR_ENCAP] = -1, | 804 | [OVS_KEY_ATTR_ENCAP] = -1, |
803 | [OVS_KEY_ATTR_PRIORITY] = sizeof(u32), | 805 | [OVS_KEY_ATTR_PRIORITY] = sizeof(u32), |
804 | [OVS_KEY_ATTR_IN_PORT] = sizeof(u32), | 806 | [OVS_KEY_ATTR_IN_PORT] = sizeof(u32), |
807 | [OVS_KEY_ATTR_SKB_MARK] = sizeof(u32), | ||
805 | [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet), | 808 | [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet), |
806 | [OVS_KEY_ATTR_VLAN] = sizeof(__be16), | 809 | [OVS_KEY_ATTR_VLAN] = sizeof(__be16), |
807 | [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16), | 810 | [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16), |
@@ -987,6 +990,10 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | |||
987 | } else { | 990 | } else { |
988 | swkey->phy.in_port = DP_MAX_PORTS; | 991 | swkey->phy.in_port = DP_MAX_PORTS; |
989 | } | 992 | } |
993 | if (attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) { | ||
994 | swkey->phy.skb_mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]); | ||
995 | attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK); | ||
996 | } | ||
990 | 997 | ||
991 | /* Data attributes. */ | 998 | /* Data attributes. */ |
992 | if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET))) | 999 | if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET))) |
@@ -1086,7 +1093,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | |||
1086 | if (err) | 1093 | if (err) |
1087 | return err; | 1094 | return err; |
1088 | } | 1095 | } |
1089 | } else if (swkey->eth.type == htons(ETH_P_ARP)) { | 1096 | } else if (swkey->eth.type == htons(ETH_P_ARP) || |
1097 | swkey->eth.type == htons(ETH_P_RARP)) { | ||
1090 | const struct ovs_key_arp *arp_key; | 1098 | const struct ovs_key_arp *arp_key; |
1091 | 1099 | ||
1092 | if (!(attrs & (1 << OVS_KEY_ATTR_ARP))) | 1100 | if (!(attrs & (1 << OVS_KEY_ATTR_ARP))) |
@@ -1113,6 +1121,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | |||
1113 | 1121 | ||
1114 | /** | 1122 | /** |
1115 | * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key. | 1123 | * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key. |
1124 | * @priority: receives the skb priority | ||
1125 | * @mark: receives the skb mark | ||
1116 | * @in_port: receives the extracted input port. | 1126 | * @in_port: receives the extracted input port. |
1117 | * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute | 1127 | * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute |
1118 | * sequence. | 1128 | * sequence. |
@@ -1122,7 +1132,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | |||
1122 | * get the metadata, that is, the parts of the flow key that cannot be | 1132 | * get the metadata, that is, the parts of the flow key that cannot be |
1123 | * extracted from the packet itself. | 1133 | * extracted from the packet itself. |
1124 | */ | 1134 | */ |
1125 | int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, | 1135 | int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, |
1126 | const struct nlattr *attr) | 1136 | const struct nlattr *attr) |
1127 | { | 1137 | { |
1128 | const struct nlattr *nla; | 1138 | const struct nlattr *nla; |
@@ -1130,6 +1140,7 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, | |||
1130 | 1140 | ||
1131 | *in_port = DP_MAX_PORTS; | 1141 | *in_port = DP_MAX_PORTS; |
1132 | *priority = 0; | 1142 | *priority = 0; |
1143 | *mark = 0; | ||
1133 | 1144 | ||
1134 | nla_for_each_nested(nla, attr, rem) { | 1145 | nla_for_each_nested(nla, attr, rem) { |
1135 | int type = nla_type(nla); | 1146 | int type = nla_type(nla); |
@@ -1148,6 +1159,10 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, | |||
1148 | return -EINVAL; | 1159 | return -EINVAL; |
1149 | *in_port = nla_get_u32(nla); | 1160 | *in_port = nla_get_u32(nla); |
1150 | break; | 1161 | break; |
1162 | |||
1163 | case OVS_KEY_ATTR_SKB_MARK: | ||
1164 | *mark = nla_get_u32(nla); | ||
1165 | break; | ||
1151 | } | 1166 | } |
1152 | } | 1167 | } |
1153 | } | 1168 | } |
@@ -1169,6 +1184,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) | |||
1169 | nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port)) | 1184 | nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port)) |
1170 | goto nla_put_failure; | 1185 | goto nla_put_failure; |
1171 | 1186 | ||
1187 | if (swkey->phy.skb_mark && | ||
1188 | nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, swkey->phy.skb_mark)) | ||
1189 | goto nla_put_failure; | ||
1190 | |||
1172 | nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key)); | 1191 | nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key)); |
1173 | if (!nla) | 1192 | if (!nla) |
1174 | goto nla_put_failure; | 1193 | goto nla_put_failure; |
@@ -1222,7 +1241,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) | |||
1222 | ipv6_key->ipv6_tclass = swkey->ip.tos; | 1241 | ipv6_key->ipv6_tclass = swkey->ip.tos; |
1223 | ipv6_key->ipv6_hlimit = swkey->ip.ttl; | 1242 | ipv6_key->ipv6_hlimit = swkey->ip.ttl; |
1224 | ipv6_key->ipv6_frag = swkey->ip.frag; | 1243 | ipv6_key->ipv6_frag = swkey->ip.frag; |
1225 | } else if (swkey->eth.type == htons(ETH_P_ARP)) { | 1244 | } else if (swkey->eth.type == htons(ETH_P_ARP) || |
1245 | swkey->eth.type == htons(ETH_P_RARP)) { | ||
1226 | struct ovs_key_arp *arp_key; | 1246 | struct ovs_key_arp *arp_key; |
1227 | 1247 | ||
1228 | nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key)); | 1248 | nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key)); |
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 14a324eb017b..a7bb60ff3b5b 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
@@ -43,6 +43,7 @@ struct sw_flow_actions { | |||
43 | struct sw_flow_key { | 43 | struct sw_flow_key { |
44 | struct { | 44 | struct { |
45 | u32 priority; /* Packet QoS priority. */ | 45 | u32 priority; /* Packet QoS priority. */ |
46 | u32 skb_mark; /* SKB mark. */ | ||
46 | u16 in_port; /* Input switch port (or DP_MAX_PORTS). */ | 47 | u16 in_port; /* Input switch port (or DP_MAX_PORTS). */ |
47 | } phy; | 48 | } phy; |
48 | struct { | 49 | struct { |
@@ -144,6 +145,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); | |||
144 | * ------ --- ------ ----- | 145 | * ------ --- ------ ----- |
145 | * OVS_KEY_ATTR_PRIORITY 4 -- 4 8 | 146 | * OVS_KEY_ATTR_PRIORITY 4 -- 4 8 |
146 | * OVS_KEY_ATTR_IN_PORT 4 -- 4 8 | 147 | * OVS_KEY_ATTR_IN_PORT 4 -- 4 8 |
148 | * OVS_KEY_ATTR_SKB_MARK 4 -- 4 8 | ||
147 | * OVS_KEY_ATTR_ETHERNET 12 -- 4 16 | 149 | * OVS_KEY_ATTR_ETHERNET 12 -- 4 16 |
148 | * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype) | 150 | * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype) |
149 | * OVS_KEY_ATTR_8021Q 4 -- 4 8 | 151 | * OVS_KEY_ATTR_8021Q 4 -- 4 8 |
@@ -153,14 +155,14 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies); | |||
153 | * OVS_KEY_ATTR_ICMPV6 2 2 4 8 | 155 | * OVS_KEY_ATTR_ICMPV6 2 2 4 8 |
154 | * OVS_KEY_ATTR_ND 28 -- 4 32 | 156 | * OVS_KEY_ATTR_ND 28 -- 4 32 |
155 | * ------------------------------------------------- | 157 | * ------------------------------------------------- |
156 | * total 144 | 158 | * total 152 |
157 | */ | 159 | */ |
158 | #define FLOW_BUFSIZE 144 | 160 | #define FLOW_BUFSIZE 152 |
159 | 161 | ||
160 | int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); | 162 | int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); |
161 | int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | 163 | int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, |
162 | const struct nlattr *); | 164 | const struct nlattr *); |
163 | int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port, | 165 | int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port, |
164 | const struct nlattr *); | 166 | const struct nlattr *); |
165 | 167 | ||
166 | #define MAX_ACTIONS_BUFSIZE (16 * 1024) | 168 | #define MAX_ACTIONS_BUFSIZE (16 * 1024) |
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index a9033481fa5e..a9327e2e48ce 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c | |||
@@ -114,6 +114,15 @@ error: | |||
114 | return ERR_PTR(err); | 114 | return ERR_PTR(err); |
115 | } | 115 | } |
116 | 116 | ||
117 | static void free_port_rcu(struct rcu_head *rcu) | ||
118 | { | ||
119 | struct netdev_vport *netdev_vport = container_of(rcu, | ||
120 | struct netdev_vport, rcu); | ||
121 | |||
122 | dev_put(netdev_vport->dev); | ||
123 | ovs_vport_free(vport_from_priv(netdev_vport)); | ||
124 | } | ||
125 | |||
117 | static void netdev_destroy(struct vport *vport) | 126 | static void netdev_destroy(struct vport *vport) |
118 | { | 127 | { |
119 | struct netdev_vport *netdev_vport = netdev_vport_priv(vport); | 128 | struct netdev_vport *netdev_vport = netdev_vport_priv(vport); |
@@ -122,10 +131,7 @@ static void netdev_destroy(struct vport *vport) | |||
122 | netdev_rx_handler_unregister(netdev_vport->dev); | 131 | netdev_rx_handler_unregister(netdev_vport->dev); |
123 | dev_set_promiscuity(netdev_vport->dev, -1); | 132 | dev_set_promiscuity(netdev_vport->dev, -1); |
124 | 133 | ||
125 | synchronize_rcu(); | 134 | call_rcu(&netdev_vport->rcu, free_port_rcu); |
126 | |||
127 | dev_put(netdev_vport->dev); | ||
128 | ovs_vport_free(vport); | ||
129 | } | 135 | } |
130 | 136 | ||
131 | const char *ovs_netdev_get_name(const struct vport *vport) | 137 | const char *ovs_netdev_get_name(const struct vport *vport) |
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h index f7072a25c604..6478079b3417 100644 --- a/net/openvswitch/vport-netdev.h +++ b/net/openvswitch/vport-netdev.h | |||
@@ -20,12 +20,15 @@ | |||
20 | #define VPORT_NETDEV_H 1 | 20 | #define VPORT_NETDEV_H 1 |
21 | 21 | ||
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/rcupdate.h> | ||
23 | 24 | ||
24 | #include "vport.h" | 25 | #include "vport.h" |
25 | 26 | ||
26 | struct vport *ovs_netdev_get_vport(struct net_device *dev); | 27 | struct vport *ovs_netdev_get_vport(struct net_device *dev); |
27 | 28 | ||
28 | struct netdev_vport { | 29 | struct netdev_vport { |
30 | struct rcu_head rcu; | ||
31 | |||
29 | struct net_device *dev; | 32 | struct net_device *dev; |
30 | }; | 33 | }; |
31 | 34 | ||
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 03779e8a2622..70af0bedbac4 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
@@ -333,8 +333,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb) | |||
333 | { | 333 | { |
334 | struct vport_percpu_stats *stats; | 334 | struct vport_percpu_stats *stats; |
335 | 335 | ||
336 | stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id()); | 336 | stats = this_cpu_ptr(vport->percpu_stats); |
337 | |||
338 | u64_stats_update_begin(&stats->sync); | 337 | u64_stats_update_begin(&stats->sync); |
339 | stats->rx_packets++; | 338 | stats->rx_packets++; |
340 | stats->rx_bytes += skb->len; | 339 | stats->rx_bytes += skb->len; |
@@ -359,7 +358,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb) | |||
359 | if (likely(sent)) { | 358 | if (likely(sent)) { |
360 | struct vport_percpu_stats *stats; | 359 | struct vport_percpu_stats *stats; |
361 | 360 | ||
362 | stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id()); | 361 | stats = this_cpu_ptr(vport->percpu_stats); |
363 | 362 | ||
364 | u64_stats_update_begin(&stats->sync); | 363 | u64_stats_update_begin(&stats->sync); |
365 | stats->tx_packets++; | 364 | stats->tx_packets++; |