diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
| -rw-r--r-- | net/openvswitch/datapath.c | 27 |
1 files changed, 25 insertions, 2 deletions
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); |
