.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2007-2014 Nicira, Inc. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of version 2 of the GNU General Public |
---|
6 | | - * License as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, but |
---|
9 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
11 | | - * General Public License for more details. |
---|
12 | | - * |
---|
13 | | - * You should have received a copy of the GNU General Public License |
---|
14 | | - * along with this program; if not, write to the Free Software |
---|
15 | | - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
---|
16 | | - * 02110-1301, USA |
---|
17 | 4 | */ |
---|
18 | 5 | |
---|
19 | 6 | #include <linux/uaccess.h> |
---|
.. | .. |
---|
72 | 59 | void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, |
---|
73 | 60 | const struct sk_buff *skb) |
---|
74 | 61 | { |
---|
75 | | - struct flow_stats *stats; |
---|
| 62 | + struct sw_flow_stats *stats; |
---|
76 | 63 | unsigned int cpu = smp_processor_id(); |
---|
77 | 64 | int len = skb->len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); |
---|
78 | 65 | |
---|
.. | .. |
---|
100 | 87 | if (likely(flow->stats_last_writer != -1) && |
---|
101 | 88 | likely(!rcu_access_pointer(flow->stats[cpu]))) { |
---|
102 | 89 | /* Try to allocate CPU-specific stats. */ |
---|
103 | | - struct flow_stats *new_stats; |
---|
| 90 | + struct sw_flow_stats *new_stats; |
---|
104 | 91 | |
---|
105 | 92 | new_stats = |
---|
106 | 93 | kmem_cache_alloc_node(flow_stats_cache, |
---|
.. | .. |
---|
147 | 134 | |
---|
148 | 135 | /* We open code this to make sure cpu 0 is always considered */ |
---|
149 | 136 | for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) { |
---|
150 | | - struct flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]); |
---|
| 137 | + struct sw_flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]); |
---|
151 | 138 | |
---|
152 | 139 | if (stats) { |
---|
153 | 140 | /* Local CPU may write on non-local stats, so we must |
---|
.. | .. |
---|
171 | 158 | |
---|
172 | 159 | /* We open code this to make sure cpu 0 is always considered */ |
---|
173 | 160 | for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) { |
---|
174 | | - struct flow_stats *stats = ovsl_dereference(flow->stats[cpu]); |
---|
| 161 | + struct sw_flow_stats *stats = ovsl_dereference(flow->stats[cpu]); |
---|
175 | 162 | |
---|
176 | 163 | if (stats) { |
---|
177 | 164 | spin_lock_bh(&stats->lock); |
---|
.. | .. |
---|
254 | 241 | |
---|
255 | 242 | static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key) |
---|
256 | 243 | { |
---|
| 244 | + unsigned short frag_off; |
---|
| 245 | + unsigned int payload_ofs = 0; |
---|
257 | 246 | unsigned int nh_ofs = skb_network_offset(skb); |
---|
258 | 247 | unsigned int nh_len; |
---|
259 | | - int payload_ofs; |
---|
260 | 248 | struct ipv6hdr *nh; |
---|
261 | | - uint8_t nexthdr; |
---|
262 | | - __be16 frag_off; |
---|
263 | | - int err; |
---|
| 249 | + int err, nexthdr, flags = 0; |
---|
264 | 250 | |
---|
265 | 251 | err = check_header(skb, nh_ofs + sizeof(*nh)); |
---|
266 | 252 | if (unlikely(err)) |
---|
267 | 253 | return err; |
---|
268 | 254 | |
---|
269 | 255 | nh = ipv6_hdr(skb); |
---|
270 | | - nexthdr = nh->nexthdr; |
---|
271 | | - payload_ofs = (u8 *)(nh + 1) - skb->data; |
---|
272 | 256 | |
---|
273 | 257 | key->ip.proto = NEXTHDR_NONE; |
---|
274 | 258 | key->ip.tos = ipv6_get_dsfield(nh); |
---|
.. | .. |
---|
277 | 261 | key->ipv6.addr.src = nh->saddr; |
---|
278 | 262 | key->ipv6.addr.dst = nh->daddr; |
---|
279 | 263 | |
---|
280 | | - payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off); |
---|
281 | | - |
---|
282 | | - if (frag_off) { |
---|
283 | | - if (frag_off & htons(~0x7)) |
---|
| 264 | + nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags); |
---|
| 265 | + if (flags & IP6_FH_F_FRAG) { |
---|
| 266 | + if (frag_off) { |
---|
284 | 267 | key->ip.frag = OVS_FRAG_TYPE_LATER; |
---|
285 | | - else |
---|
286 | | - key->ip.frag = OVS_FRAG_TYPE_FIRST; |
---|
| 268 | + key->ip.proto = NEXTHDR_FRAGMENT; |
---|
| 269 | + return 0; |
---|
| 270 | + } |
---|
| 271 | + key->ip.frag = OVS_FRAG_TYPE_FIRST; |
---|
287 | 272 | } else { |
---|
288 | 273 | key->ip.frag = OVS_FRAG_TYPE_NONE; |
---|
289 | 274 | } |
---|
290 | 275 | |
---|
291 | | - /* Delayed handling of error in ipv6_skip_exthdr() as it |
---|
292 | | - * always sets frag_off to a valid value which may be |
---|
| 276 | + /* Delayed handling of error in ipv6_find_hdr() as it |
---|
| 277 | + * always sets flags and frag_off to a valid value which may be |
---|
293 | 278 | * used to set key->ip.frag above. |
---|
294 | 279 | */ |
---|
295 | | - if (unlikely(payload_ofs < 0)) |
---|
| 280 | + if (unlikely(nexthdr < 0)) |
---|
296 | 281 | return -EPROTO; |
---|
297 | 282 | |
---|
298 | 283 | nh_len = payload_ofs - nh_ofs; |
---|
.. | .. |
---|
329 | 314 | return -ENOMEM; |
---|
330 | 315 | |
---|
331 | 316 | vh = (struct vlan_head *)skb->data; |
---|
332 | | - key_vh->tci = vh->tci | htons(VLAN_TAG_PRESENT); |
---|
| 317 | + key_vh->tci = vh->tci | htons(VLAN_CFI_MASK); |
---|
333 | 318 | key_vh->tpid = vh->tpid; |
---|
334 | 319 | |
---|
335 | 320 | if (unlikely(untag_vlan)) { |
---|
.. | .. |
---|
362 | 347 | int res; |
---|
363 | 348 | |
---|
364 | 349 | if (skb_vlan_tag_present(skb)) { |
---|
365 | | - key->eth.vlan.tci = htons(skb->vlan_tci); |
---|
| 350 | + key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK); |
---|
366 | 351 | key->eth.vlan.tpid = skb->vlan_proto; |
---|
367 | 352 | } else { |
---|
368 | 353 | /* Parse outer vlan tag in the non-accelerated case. */ |
---|
.. | .. |
---|
538 | 523 | } |
---|
539 | 524 | |
---|
540 | 525 | /** |
---|
541 | | - * key_extract - extracts a flow key from an Ethernet frame. |
---|
| 526 | + * key_extract_l3l4 - extracts L3/L4 header information. |
---|
542 | 527 | * @skb: sk_buff that contains the frame, with skb->data pointing to the |
---|
543 | | - * Ethernet header |
---|
| 528 | + * L3 header |
---|
544 | 529 | * @key: output flow key |
---|
545 | 530 | * |
---|
546 | | - * The caller must ensure that skb->len >= ETH_HLEN. |
---|
547 | | - * |
---|
548 | | - * Returns 0 if successful, otherwise a negative errno value. |
---|
549 | | - * |
---|
550 | | - * Initializes @skb header fields as follows: |
---|
551 | | - * |
---|
552 | | - * - skb->mac_header: the L2 header. |
---|
553 | | - * |
---|
554 | | - * - skb->network_header: just past the L2 header, or just past the |
---|
555 | | - * VLAN header, to the first byte of the L2 payload. |
---|
556 | | - * |
---|
557 | | - * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 |
---|
558 | | - * on output, then just past the IP header, if one is present and |
---|
559 | | - * of a correct length, otherwise the same as skb->network_header. |
---|
560 | | - * For other key->eth.type values it is left untouched. |
---|
561 | | - * |
---|
562 | | - * - skb->protocol: the type of the data starting at skb->network_header. |
---|
563 | | - * Equals to key->eth.type. |
---|
564 | 531 | */ |
---|
565 | | -static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) |
---|
| 532 | +static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key) |
---|
566 | 533 | { |
---|
567 | 534 | int error; |
---|
568 | | - struct ethhdr *eth; |
---|
569 | | - |
---|
570 | | - /* Flags are always used as part of stats */ |
---|
571 | | - key->tp.flags = 0; |
---|
572 | | - |
---|
573 | | - skb_reset_mac_header(skb); |
---|
574 | | - |
---|
575 | | - /* Link layer. */ |
---|
576 | | - clear_vlan(key); |
---|
577 | | - if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { |
---|
578 | | - if (unlikely(eth_type_vlan(skb->protocol))) |
---|
579 | | - return -EINVAL; |
---|
580 | | - |
---|
581 | | - skb_reset_network_header(skb); |
---|
582 | | - key->eth.type = skb->protocol; |
---|
583 | | - } else { |
---|
584 | | - eth = eth_hdr(skb); |
---|
585 | | - ether_addr_copy(key->eth.src, eth->h_source); |
---|
586 | | - ether_addr_copy(key->eth.dst, eth->h_dest); |
---|
587 | | - |
---|
588 | | - __skb_pull(skb, 2 * ETH_ALEN); |
---|
589 | | - /* We are going to push all headers that we pull, so no need to |
---|
590 | | - * update skb->csum here. |
---|
591 | | - */ |
---|
592 | | - |
---|
593 | | - if (unlikely(parse_vlan(skb, key))) |
---|
594 | | - return -ENOMEM; |
---|
595 | | - |
---|
596 | | - key->eth.type = parse_ethertype(skb); |
---|
597 | | - if (unlikely(key->eth.type == htons(0))) |
---|
598 | | - return -ENOMEM; |
---|
599 | | - |
---|
600 | | - /* Multiple tagged packets need to retain TPID to satisfy |
---|
601 | | - * skb_vlan_pop(), which will later shift the ethertype into |
---|
602 | | - * skb->protocol. |
---|
603 | | - */ |
---|
604 | | - if (key->eth.cvlan.tci & htons(VLAN_TAG_PRESENT)) |
---|
605 | | - skb->protocol = key->eth.cvlan.tpid; |
---|
606 | | - else |
---|
607 | | - skb->protocol = key->eth.type; |
---|
608 | | - |
---|
609 | | - skb_reset_network_header(skb); |
---|
610 | | - __skb_push(skb, skb->data - skb_mac_header(skb)); |
---|
611 | | - } |
---|
612 | | - skb_reset_mac_len(skb); |
---|
613 | 535 | |
---|
614 | 536 | /* Network layer. */ |
---|
615 | 537 | if (key->eth.type == htons(ETH_P_IP)) { |
---|
.. | .. |
---|
638 | 560 | offset = nh->frag_off & htons(IP_OFFSET); |
---|
639 | 561 | if (offset) { |
---|
640 | 562 | key->ip.frag = OVS_FRAG_TYPE_LATER; |
---|
| 563 | + memset(&key->tp, 0, sizeof(key->tp)); |
---|
641 | 564 | return 0; |
---|
642 | 565 | } |
---|
643 | 566 | if (nh->frag_off & htons(IP_MF) || |
---|
.. | .. |
---|
714 | 637 | memset(&key->ipv4, 0, sizeof(key->ipv4)); |
---|
715 | 638 | } |
---|
716 | 639 | } else if (eth_p_mpls(key->eth.type)) { |
---|
717 | | - size_t stack_len = MPLS_HLEN; |
---|
| 640 | + u8 label_count = 1; |
---|
718 | 641 | |
---|
| 642 | + memset(&key->mpls, 0, sizeof(key->mpls)); |
---|
719 | 643 | skb_set_inner_network_header(skb, skb->mac_len); |
---|
720 | 644 | while (1) { |
---|
721 | 645 | __be32 lse; |
---|
722 | 646 | |
---|
723 | | - error = check_header(skb, skb->mac_len + stack_len); |
---|
| 647 | + error = check_header(skb, skb->mac_len + |
---|
| 648 | + label_count * MPLS_HLEN); |
---|
724 | 649 | if (unlikely(error)) |
---|
725 | 650 | return 0; |
---|
726 | 651 | |
---|
727 | 652 | memcpy(&lse, skb_inner_network_header(skb), MPLS_HLEN); |
---|
728 | 653 | |
---|
729 | | - if (stack_len == MPLS_HLEN) |
---|
730 | | - memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN); |
---|
| 654 | + if (label_count <= MPLS_LABEL_DEPTH) |
---|
| 655 | + memcpy(&key->mpls.lse[label_count - 1], &lse, |
---|
| 656 | + MPLS_HLEN); |
---|
731 | 657 | |
---|
732 | | - skb_set_inner_network_header(skb, skb->mac_len + stack_len); |
---|
| 658 | + skb_set_inner_network_header(skb, skb->mac_len + |
---|
| 659 | + label_count * MPLS_HLEN); |
---|
733 | 660 | if (lse & htonl(MPLS_LS_S_MASK)) |
---|
734 | 661 | break; |
---|
735 | 662 | |
---|
736 | | - stack_len += MPLS_HLEN; |
---|
| 663 | + label_count++; |
---|
737 | 664 | } |
---|
| 665 | + if (label_count > MPLS_LABEL_DEPTH) |
---|
| 666 | + label_count = MPLS_LABEL_DEPTH; |
---|
| 667 | + |
---|
| 668 | + key->mpls.num_labels_mask = GENMASK(label_count - 1, 0); |
---|
738 | 669 | } else if (key->eth.type == htons(ETH_P_IPV6)) { |
---|
739 | 670 | int nh_len; /* IPv6 Header + Extensions */ |
---|
740 | 671 | |
---|
.. | .. |
---|
744 | 675 | case -EINVAL: |
---|
745 | 676 | memset(&key->ip, 0, sizeof(key->ip)); |
---|
746 | 677 | memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr)); |
---|
747 | | - /* fall-through */ |
---|
| 678 | + fallthrough; |
---|
748 | 679 | case -EPROTO: |
---|
749 | 680 | skb->transport_header = skb->network_header; |
---|
750 | 681 | error = 0; |
---|
.. | .. |
---|
755 | 686 | return error; |
---|
756 | 687 | } |
---|
757 | 688 | |
---|
758 | | - if (key->ip.frag == OVS_FRAG_TYPE_LATER) |
---|
| 689 | + if (key->ip.frag == OVS_FRAG_TYPE_LATER) { |
---|
| 690 | + memset(&key->tp, 0, sizeof(key->tp)); |
---|
759 | 691 | return 0; |
---|
| 692 | + } |
---|
760 | 693 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) |
---|
761 | 694 | key->ip.frag = OVS_FRAG_TYPE_FIRST; |
---|
762 | 695 | |
---|
.. | .. |
---|
803 | 736 | return 0; |
---|
804 | 737 | } |
---|
805 | 738 | |
---|
| 739 | +/** |
---|
| 740 | + * key_extract - extracts a flow key from an Ethernet frame. |
---|
| 741 | + * @skb: sk_buff that contains the frame, with skb->data pointing to the |
---|
| 742 | + * Ethernet header |
---|
| 743 | + * @key: output flow key |
---|
| 744 | + * |
---|
| 745 | + * The caller must ensure that skb->len >= ETH_HLEN. |
---|
| 746 | + * |
---|
| 747 | + * Returns 0 if successful, otherwise a negative errno value. |
---|
| 748 | + * |
---|
| 749 | + * Initializes @skb header fields as follows: |
---|
| 750 | + * |
---|
| 751 | + * - skb->mac_header: the L2 header. |
---|
| 752 | + * |
---|
| 753 | + * - skb->network_header: just past the L2 header, or just past the |
---|
| 754 | + * VLAN header, to the first byte of the L2 payload. |
---|
| 755 | + * |
---|
| 756 | + * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 |
---|
| 757 | + * on output, then just past the IP header, if one is present and |
---|
| 758 | + * of a correct length, otherwise the same as skb->network_header. |
---|
| 759 | + * For other key->eth.type values it is left untouched. |
---|
| 760 | + * |
---|
| 761 | + * - skb->protocol: the type of the data starting at skb->network_header. |
---|
| 762 | + * Equals to key->eth.type. |
---|
| 763 | + */ |
---|
| 764 | +static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) |
---|
| 765 | +{ |
---|
| 766 | + struct ethhdr *eth; |
---|
| 767 | + |
---|
| 768 | + /* Flags are always used as part of stats */ |
---|
| 769 | + key->tp.flags = 0; |
---|
| 770 | + |
---|
| 771 | + skb_reset_mac_header(skb); |
---|
| 772 | + |
---|
| 773 | + /* Link layer. */ |
---|
| 774 | + clear_vlan(key); |
---|
| 775 | + if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { |
---|
| 776 | + if (unlikely(eth_type_vlan(skb->protocol))) |
---|
| 777 | + return -EINVAL; |
---|
| 778 | + |
---|
| 779 | + skb_reset_network_header(skb); |
---|
| 780 | + key->eth.type = skb->protocol; |
---|
| 781 | + } else { |
---|
| 782 | + eth = eth_hdr(skb); |
---|
| 783 | + ether_addr_copy(key->eth.src, eth->h_source); |
---|
| 784 | + ether_addr_copy(key->eth.dst, eth->h_dest); |
---|
| 785 | + |
---|
| 786 | + __skb_pull(skb, 2 * ETH_ALEN); |
---|
| 787 | + /* We are going to push all headers that we pull, so no need to |
---|
| 788 | + * update skb->csum here. |
---|
| 789 | + */ |
---|
| 790 | + |
---|
| 791 | + if (unlikely(parse_vlan(skb, key))) |
---|
| 792 | + return -ENOMEM; |
---|
| 793 | + |
---|
| 794 | + key->eth.type = parse_ethertype(skb); |
---|
| 795 | + if (unlikely(key->eth.type == htons(0))) |
---|
| 796 | + return -ENOMEM; |
---|
| 797 | + |
---|
| 798 | + /* Multiple tagged packets need to retain TPID to satisfy |
---|
| 799 | + * skb_vlan_pop(), which will later shift the ethertype into |
---|
| 800 | + * skb->protocol. |
---|
| 801 | + */ |
---|
| 802 | + if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK)) |
---|
| 803 | + skb->protocol = key->eth.cvlan.tpid; |
---|
| 804 | + else |
---|
| 805 | + skb->protocol = key->eth.type; |
---|
| 806 | + |
---|
| 807 | + skb_reset_network_header(skb); |
---|
| 808 | + __skb_push(skb, skb->data - skb_mac_header(skb)); |
---|
| 809 | + } |
---|
| 810 | + |
---|
| 811 | + skb_reset_mac_len(skb); |
---|
| 812 | + |
---|
| 813 | + /* Fill out L3/L4 key info, if any */ |
---|
| 814 | + return key_extract_l3l4(skb, key); |
---|
| 815 | +} |
---|
| 816 | + |
---|
| 817 | +/* In the case of conntrack fragment handling it expects L3 headers, |
---|
| 818 | + * add a helper. |
---|
| 819 | + */ |
---|
| 820 | +int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key) |
---|
| 821 | +{ |
---|
| 822 | + return key_extract_l3l4(skb, key); |
---|
| 823 | +} |
---|
| 824 | + |
---|
806 | 825 | int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key) |
---|
807 | 826 | { |
---|
808 | 827 | int res; |
---|
.. | .. |
---|
831 | 850 | int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, |
---|
832 | 851 | struct sk_buff *skb, struct sw_flow_key *key) |
---|
833 | 852 | { |
---|
| 853 | +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) |
---|
| 854 | + struct tc_skb_ext *tc_ext; |
---|
| 855 | +#endif |
---|
834 | 856 | int res, err; |
---|
835 | 857 | |
---|
836 | 858 | /* Extract metadata from packet. */ |
---|
.. | .. |
---|
863 | 885 | if (res < 0) |
---|
864 | 886 | return res; |
---|
865 | 887 | key->mac_proto = res; |
---|
| 888 | + |
---|
| 889 | +#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT) |
---|
| 890 | + if (static_branch_unlikely(&tc_recirc_sharing_support)) { |
---|
| 891 | + tc_ext = skb_ext_find(skb, TC_SKB_EXT); |
---|
| 892 | + key->recirc_id = tc_ext ? tc_ext->chain : 0; |
---|
| 893 | + OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0; |
---|
| 894 | + } else { |
---|
| 895 | + key->recirc_id = 0; |
---|
| 896 | + } |
---|
| 897 | +#else |
---|
866 | 898 | key->recirc_id = 0; |
---|
| 899 | +#endif |
---|
867 | 900 | |
---|
868 | 901 | err = key_extract(skb, key); |
---|
869 | 902 | if (!err) |
---|