Implements ip_defrag action in Linux kenrel using ip_defrag kernel APIs. Signed-off-by: Andy Zhou <az...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev