[ovs-dev] [IP DEFRAG ACTION RFC 2/2] datapath: add ip_defag action

Andy Zhou azhou at nicira.com
Mon Nov 10 22:52:54 UTC 2014


Implements ip_defrag action in Linux kenrel using ip_defrag kernel APIs.

Signed-off-by: Andy Zhou <azhou at nicira.com>
---
 datapath/actions.c      | 39 ++++++++++++++++++++++++++++++++++++++-
 datapath/flow_netlink.c |  6 +++++-
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 5a1dbe2..668d44f 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -826,6 +826,38 @@ static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
 	return 0;
 }
 
+static int ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
+{
+	int err;
+
+	local_bh_disable();
+	err = ip_defrag(skb, user);
+	local_bh_enable();
+
+	if (!err) {
+		ip_send_check(ip_hdr(skb));
+		skb->ignore_df = 1;
+	}
+
+	return err;
+}
+
+static int execute_ip_defrag(struct sk_buff *skb, struct sw_flow_key *key,
+			     const struct ovs_action_ip_defrag *act_ip_defrag)
+{
+	if (key->eth.type == htons(ETH_P_IP)) {
+		if (ip_is_fragment(ip_hdr(skb))) {
+			enum ip_defrag_users user;
+
+			user = IP_DEFRAG_CONNTRACK_IN + act_ip_defrag->zone;
+			if (ipv4_gather_frags(skb, user))
+				return -EINPROGRESS;
+		}
+	}
+
+	return 0;
+}
+
 /* Execute a list of actions against 'skb'. */
 static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			      struct sw_flow_key *key,
@@ -902,10 +934,15 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 		case OVS_ACTION_ATTR_SAMPLE:
 			err = sample(dp, skb, key, a);
 			break;
+
+		case OVS_ACTION_ATTR_IP_DEFRAG:
+			err = execute_ip_defrag(skb, key, nla_data(a));
+			break;
 		}
 
 		if (unlikely(err)) {
-			kfree_skb(skb);
+			if (err != -EINPROGRESS)
+				kfree_skb(skb);
 			return err;
 		}
 	}
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 503cf63..d96ad65 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -1782,7 +1782,8 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr,
 			[OVS_ACTION_ATTR_POP_VLAN] = 0,
 			[OVS_ACTION_ATTR_SET] = (u32)-1,
 			[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
-			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash)
+			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
+			[OVS_ACTION_ATTR_IP_DEFRAG] = sizeof(struct ovs_action_ip_defrag)
 		};
 		const struct ovs_action_push_vlan *vlan;
 		int type = nla_type(a);
@@ -1899,6 +1900,9 @@ static int __ovs_nla_copy_actions(const struct nlattr *attr,
 			skip_copy = true;
 			break;
 
+		case OVS_ACTION_ATTR_IP_DEFRAG:
+			break;
+
 		default:
 			OVS_NLERR(log, "Unknown Action type %d", type);
 			return -EINVAL;
-- 
1.9.1




More information about the dev mailing list