openvswitch: move key and ovs_cb update out of handle_fragments
[linux-2.6-microblaze.git] / net / openvswitch / conntrack.c
index 4be877a..211e058 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;
        }