diff options
Diffstat (limited to 'net/openvswitch/flow.c')
-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) |