aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2014-10-03 18:35:29 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-06 00:32:20 -0400
commit0714812134d7dcadeb7ecfbfeb18788aa7e1eaac (patch)
tree881bb28da2ca3882fd0a6a30574e98787d5feafb /net/openvswitch
parent0b5e8b8eeae40bae6ad7c7e91c97c3c0d0e57882 (diff)
openvswitch: Eliminate memset() from flow_extract.
As new protocols are added, the size of the flow key tends to increase although few protocols care about all of the fields. In order to optimize this for hashing and matching, OVS uses a variable length portion of the key. However, when fields are extracted from the packet we must still zero out the entire key. This is no longer necessary now that OVS implements masking. Any fields (or holes in the structure) which are not part of a given protocol will be by definition not part of the mask and zeroed out during lookup. Furthermore, since masking already uses variable length keys this zeroing operation automatically benefits as well. In principle, the only thing that needs to be done at this point is remove the memset() at the beginning of flow. However, some fields assume that they are initialized to zero, which now must be done explicitly. In addition, in the event of an error we must also zero out corresponding fields to signal that there is no valid data present. These increase the total amount of code but very little of it is executed in non-error situations. Removing the memset() reduces the profile of ovs_flow_extract() from 0.64% to 0.56% when tested with large packets on a 10G link. Suggested-by: Pravin Shelar <pshelar@nicira.com> Signed-off-by: Jesse Gross <jesse@nicira.com> Signed-off-by: Andy Zhou <azhou@nicira.com> Acked-by: Pravin B Shelar <pshelar@nicira.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/flow.c54
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)