openvswitch: move key and ovs_cb update out of handle_fragments
authorXin Long <lucien.xin@gmail.com>
Tue, 7 Feb 2023 22:52:08 +0000 (17:52 -0500)
committerJakub Kicinski <kuba@kernel.org>
Sat, 11 Feb 2023 00:23:03 +0000 (16:23 -0800)
This patch has no functional changes and just moves key and ovs_cb update
out of handle_fragments, and skb_clear_hash() and skb->ignore_df change
into handle_fragments(), to make it easier to move the duplicate code
from handle_fragments() into nf_conntrack_ovs later.

Note that it changes to pass info->family to handle_fragments() instead
of key for the packet type check, as info->family is set according to
key->eth.type in ovs_ct_copy_action() when creating the action.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Reviewed-by: Aaron Conole <aconole@redhat.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/openvswitch/conntrack.c

index 4be877acc7f05dbbc560d8d34f43f633eede157b..211e05828fe5fc2228794d6265139ffdfa4bfc44 100644 (file)
@@ -438,13 +438,12 @@ static int ovs_ct_set_labels(struct nf_conn *ct, struct sw_flow_key *key,
 /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
  * value if 'skb' is freed.
  */
-static int handle_fragments(struct net *net, struct sw_flow_key *key,
-                           u16 zone, struct sk_buff *skb)
+static int handle_fragments(struct net *net, struct sk_buff *skb,
+                           u16 zone, u8 family, u8 *proto, u16 *mru)
 {
-       struct ovs_skb_cb ovs_cb = *OVS_CB(skb);
        int err;
 
-       if (key->eth.type == htons(ETH_P_IP)) {
+       if (family == NFPROTO_IPV4) {
                enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
 
                memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
@@ -452,9 +451,9 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                if (err)
                        return err;
 
-               ovs_cb.mru = IPCB(skb)->frag_max_size;
+               *mru = IPCB(skb)->frag_max_size;
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
-       } else if (key->eth.type == htons(ETH_P_IPV6)) {
+       } else if (family == NFPROTO_IPV6) {
                enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
 
                memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
@@ -465,22 +464,35 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                        return err;
                }
 
-               key->ip.proto = ipv6_hdr(skb)->nexthdr;
-               ovs_cb.mru = IP6CB(skb)->frag_max_size;
+               *proto = ipv6_hdr(skb)->nexthdr;
+               *mru = IP6CB(skb)->frag_max_size;
 #endif
        } else {
                kfree_skb(skb);
                return -EPFNOSUPPORT;
        }
 
+       skb_clear_hash(skb);
+       skb->ignore_df = 1;
+
+       return 0;
+}
+
+static int ovs_ct_handle_fragments(struct net *net, struct sw_flow_key *key,
+                                  u16 zone, int family, struct sk_buff *skb)
+{
+       struct ovs_skb_cb ovs_cb = *OVS_CB(skb);
+       int err;
+
+       err = handle_fragments(net, skb, zone, family, &key->ip.proto, &ovs_cb.mru);
+       if (err)
+               return err;
+
        /* The key extracted from the fragment that completed this datagram
         * likely didn't have an L4 header, so regenerate it.
         */
        ovs_flow_key_update_l3l4(skb, key);
-
        key->ip.frag = OVS_FRAG_TYPE_NONE;
-       skb_clear_hash(skb);
-       skb->ignore_df = 1;
        *OVS_CB(skb) = ovs_cb;
 
        return 0;
@@ -1112,7 +1124,8 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
        }
 
        if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
-               err = handle_fragments(net, key, info->zone.id, skb);
+               err = ovs_ct_handle_fragments(net, key, info->zone.id,
+                                             info->family, skb);
                if (err)
                        return err;
        }