diff options
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/flow.c | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 4010423f2831..913bdc1a83c0 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
| @@ -462,6 +462,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 462 | * update skb->csum here. | 462 | * update skb->csum here. |
| 463 | */ | 463 | */ |
| 464 | 464 | ||
| 465 | key->eth.tci = 0; | ||
| 465 | if (vlan_tx_tag_present(skb)) | 466 | if (vlan_tx_tag_present(skb)) |
| 466 | key->eth.tci = htons(skb->vlan_tci); | 467 | key->eth.tci = htons(skb->vlan_tci); |
| 467 | else if (eth->h_proto == htons(ETH_P_8021Q)) | 468 | else if (eth->h_proto == htons(ETH_P_8021Q)) |
| @@ -482,6 +483,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 482 | 483 | ||
| 483 | error = check_iphdr(skb); | 484 | error = check_iphdr(skb); |
| 484 | if (unlikely(error)) { | 485 | if (unlikely(error)) { |
| 486 | memset(&key->ip, 0, sizeof(key->ip)); | ||
| 487 | memset(&key->ipv4, 0, sizeof(key->ipv4)); | ||
| 485 | if (error == -EINVAL) { | 488 | if (error == -EINVAL) { |
| 486 | skb->transport_header = skb->network_header; | 489 | skb->transport_header = skb->network_header; |
| 487 | error = 0; | 490 | error = 0; |
| @@ -503,8 +506,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 503 | return 0; | 506 | return 0; |
| 504 | } | 507 | } |
| 505 | if (nh->frag_off & htons(IP_MF) || | 508 | if (nh->frag_off & htons(IP_MF) || |
| 506 | skb_shinfo(skb)->gso_type & SKB_GSO_UDP) | 509 | skb_shinfo(skb)->gso_type & SKB_GSO_UDP) |
| 507 | key->ip.frag = OVS_FRAG_TYPE_FIRST; | 510 | key->ip.frag = OVS_FRAG_TYPE_FIRST; |
| 511 | else | ||
| 512 | key->ip.frag = OVS_FRAG_TYPE_NONE; | ||
| 508 | 513 | ||
| 509 | /* Transport layer. */ | 514 | /* Transport layer. */ |
| 510 | if (key->ip.proto == IPPROTO_TCP) { | 515 | if (key->ip.proto == IPPROTO_TCP) { |
| @@ -513,18 +518,25 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 513 | key->tp.src = tcp->source; | 518 | key->tp.src = tcp->source; |
| 514 | key->tp.dst = tcp->dest; | 519 | key->tp.dst = tcp->dest; |
| 515 | key->tp.flags = TCP_FLAGS_BE16(tcp); | 520 | key->tp.flags = TCP_FLAGS_BE16(tcp); |
| 521 | } else { | ||
| 522 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 516 | } | 523 | } |
| 524 | |||
| 517 | } else if (key->ip.proto == IPPROTO_UDP) { | 525 | } else if (key->ip.proto == IPPROTO_UDP) { |
| 518 | if (udphdr_ok(skb)) { | 526 | if (udphdr_ok(skb)) { |
| 519 | struct udphdr *udp = udp_hdr(skb); | 527 | struct udphdr *udp = udp_hdr(skb); |
| 520 | key->tp.src = udp->source; | 528 | key->tp.src = udp->source; |
| 521 | key->tp.dst = udp->dest; | 529 | key->tp.dst = udp->dest; |
| 530 | } else { | ||
| 531 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 522 | } | 532 | } |
| 523 | } else if (key->ip.proto == IPPROTO_SCTP) { | 533 | } else if (key->ip.proto == IPPROTO_SCTP) { |
| 524 | if (sctphdr_ok(skb)) { | 534 | if (sctphdr_ok(skb)) { |
| 525 | struct sctphdr *sctp = sctp_hdr(skb); | 535 | struct sctphdr *sctp = sctp_hdr(skb); |
| 526 | key->tp.src = sctp->source; | 536 | key->tp.src = sctp->source; |
| 527 | key->tp.dst = sctp->dest; | 537 | key->tp.dst = sctp->dest; |
| 538 | } else { | ||
| 539 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 528 | } | 540 | } |
| 529 | } else if (key->ip.proto == IPPROTO_ICMP) { | 541 | } else if (key->ip.proto == IPPROTO_ICMP) { |
| 530 | if (icmphdr_ok(skb)) { | 542 | if (icmphdr_ok(skb)) { |
| @@ -534,33 +546,44 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 534 | * them in 16-bit network byte order. */ | 546 | * them in 16-bit network byte order. */ |
| 535 | key->tp.src = htons(icmp->type); | 547 | key->tp.src = htons(icmp->type); |
| 536 | key->tp.dst = htons(icmp->code); | 548 | key->tp.dst = htons(icmp->code); |
| 549 | } else { | ||
| 550 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 537 | } | 551 | } |
| 538 | } | 552 | } |
| 539 | 553 | ||
| 540 | } else if ((key->eth.type == htons(ETH_P_ARP) || | 554 | } else if (key->eth.type == htons(ETH_P_ARP) || |
| 541 | key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) { | 555 | key->eth.type == htons(ETH_P_RARP)) { |
| 542 | struct arp_eth_header *arp; | 556 | struct arp_eth_header *arp; |
| 543 | 557 | ||
| 544 | arp = (struct arp_eth_header *)skb_network_header(skb); | 558 | arp = (struct arp_eth_header *)skb_network_header(skb); |
| 545 | 559 | ||
| 546 | if (arp->ar_hrd == htons(ARPHRD_ETHER) | 560 | if (arphdr_ok(skb) && |
| 547 | && arp->ar_pro == htons(ETH_P_IP) | 561 | arp->ar_hrd == htons(ARPHRD_ETHER) && |
| 548 | && arp->ar_hln == ETH_ALEN | 562 | arp->ar_pro == htons(ETH_P_IP) && |
| 549 | && arp->ar_pln == 4) { | 563 | arp->ar_hln == ETH_ALEN && |
| 564 | arp->ar_pln == 4) { | ||
| 550 | 565 | ||
| 551 | /* We only match on the lower 8 bits of the opcode. */ | 566 | /* We only match on the lower 8 bits of the opcode. */ |
| 552 | if (ntohs(arp->ar_op) <= 0xff) | 567 | if (ntohs(arp->ar_op) <= 0xff) |
| 553 | key->ip.proto = ntohs(arp->ar_op); | 568 | key->ip.proto = ntohs(arp->ar_op); |
| 569 | else | ||
| 570 | key->ip.proto = 0; | ||
| 571 | |||
| 554 | memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src)); | 572 | memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src)); |
| 555 | memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst)); | 573 | memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst)); |
| 556 | ether_addr_copy(key->ipv4.arp.sha, arp->ar_sha); | 574 | ether_addr_copy(key->ipv4.arp.sha, arp->ar_sha); |
| 557 | ether_addr_copy(key->ipv4.arp.tha, arp->ar_tha); | 575 | ether_addr_copy(key->ipv4.arp.tha, arp->ar_tha); |
| 576 | } else { | ||
| 577 | memset(&key->ip, 0, sizeof(key->ip)); | ||
| 578 | memset(&key->ipv4, 0, sizeof(key->ipv4)); | ||
| 558 | } | 579 | } |
| 559 | } else if (key->eth.type == htons(ETH_P_IPV6)) { | 580 | } else if (key->eth.type == htons(ETH_P_IPV6)) { |
| 560 | int nh_len; /* IPv6 Header + Extensions */ | 581 | int nh_len; /* IPv6 Header + Extensions */ |
| 561 | 582 | ||
| 562 | nh_len = parse_ipv6hdr(skb, key); | 583 | nh_len = parse_ipv6hdr(skb, key); |
| 563 | if (unlikely(nh_len < 0)) { | 584 | if (unlikely(nh_len < 0)) { |
| 585 | memset(&key->ip, 0, sizeof(key->ip)); | ||
| 586 | memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr)); | ||
| 564 | if (nh_len == -EINVAL) { | 587 | if (nh_len == -EINVAL) { |
| 565 | skb->transport_header = skb->network_header; | 588 | skb->transport_header = skb->network_header; |
| 566 | error = 0; | 589 | error = 0; |
| @@ -582,24 +605,32 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 582 | key->tp.src = tcp->source; | 605 | key->tp.src = tcp->source; |
| 583 | key->tp.dst = tcp->dest; | 606 | key->tp.dst = tcp->dest; |
| 584 | key->tp.flags = TCP_FLAGS_BE16(tcp); | 607 | key->tp.flags = TCP_FLAGS_BE16(tcp); |
| 608 | } else { | ||
| 609 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 585 | } | 610 | } |
| 586 | } else if (key->ip.proto == NEXTHDR_UDP) { | 611 | } else if (key->ip.proto == NEXTHDR_UDP) { |
| 587 | if (udphdr_ok(skb)) { | 612 | if (udphdr_ok(skb)) { |
| 588 | struct udphdr *udp = udp_hdr(skb); | 613 | struct udphdr *udp = udp_hdr(skb); |
| 589 | key->tp.src = udp->source; | 614 | key->tp.src = udp->source; |
| 590 | key->tp.dst = udp->dest; | 615 | key->tp.dst = udp->dest; |
| 616 | } else { | ||
| 617 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 591 | } | 618 | } |
| 592 | } else if (key->ip.proto == NEXTHDR_SCTP) { | 619 | } else if (key->ip.proto == NEXTHDR_SCTP) { |
| 593 | if (sctphdr_ok(skb)) { | 620 | if (sctphdr_ok(skb)) { |
| 594 | struct sctphdr *sctp = sctp_hdr(skb); | 621 | struct sctphdr *sctp = sctp_hdr(skb); |
| 595 | key->tp.src = sctp->source; | 622 | key->tp.src = sctp->source; |
| 596 | key->tp.dst = sctp->dest; | 623 | key->tp.dst = sctp->dest; |
| 624 | } else { | ||
| 625 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 597 | } | 626 | } |
| 598 | } else if (key->ip.proto == NEXTHDR_ICMP) { | 627 | } else if (key->ip.proto == NEXTHDR_ICMP) { |
| 599 | if (icmp6hdr_ok(skb)) { | 628 | if (icmp6hdr_ok(skb)) { |
| 600 | error = parse_icmpv6(skb, key, nh_len); | 629 | error = parse_icmpv6(skb, key, nh_len); |
| 601 | if (error) | 630 | if (error) |
| 602 | return error; | 631 | return error; |
| 632 | } else { | ||
| 633 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 603 | } | 634 | } |
| 604 | } | 635 | } |
| 605 | } | 636 | } |
| @@ -615,13 +646,19 @@ int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key, | |||
| 615 | struct sk_buff *skb, struct sw_flow_key *key) | 646 | struct sk_buff *skb, struct sw_flow_key *key) |
| 616 | { | 647 | { |
| 617 | /* Extract metadata from packet. */ | 648 | /* Extract metadata from packet. */ |
| 618 | memset(key, 0, sizeof(*key)); | ||
| 619 | if (tun_key) | 649 | if (tun_key) |
| 620 | memcpy(&key->tun_key, tun_key, sizeof(key->tun_key)); | 650 | memcpy(&key->tun_key, tun_key, sizeof(key->tun_key)); |
| 651 | else | ||
| 652 | memset(&key->tun_key, 0, sizeof(key->tun_key)); | ||
| 621 | 653 | ||
| 622 | key->phy.priority = skb->priority; | 654 | key->phy.priority = skb->priority; |
| 623 | key->phy.in_port = OVS_CB(skb)->input_vport->port_no; | 655 | key->phy.in_port = OVS_CB(skb)->input_vport->port_no; |
| 624 | key->phy.skb_mark = skb->mark; | 656 | key->phy.skb_mark = skb->mark; |
| 657 | key->ovs_flow_hash = 0; | ||
| 658 | key->recirc_id = 0; | ||
| 659 | |||
| 660 | /* Flags are always used as part of stats */ | ||
| 661 | key->tp.flags = 0; | ||
| 625 | 662 | ||
| 626 | return key_extract(skb, key); | 663 | return key_extract(skb, key); |
| 627 | } | 664 | } |
| @@ -632,7 +669,6 @@ int ovs_flow_key_extract_userspace(const struct nlattr *attr, | |||
| 632 | { | 669 | { |
| 633 | int err; | 670 | int err; |
| 634 | 671 | ||
| 635 | memset(key, 0, sizeof(*key)); | ||
| 636 | /* Extract metadata from netlink attributes. */ | 672 | /* Extract metadata from netlink attributes. */ |
| 637 | err = ovs_nla_get_flow_metadata(attr, key); | 673 | err = ovs_nla_get_flow_metadata(attr, key); |
| 638 | if (err) | 674 | if (err) |
