aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorYifeng Sun <pkusunyifeng@gmail.com>2018-07-02 11:18:03 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-07 22:13:25 -0400
commitb233504033dbd65740e59681820ccfd0a2a8ec53 (patch)
tree345441a88e44d3c9f0fd59327c4b2c138367f1e8 /net/openvswitch
parent20fbdc35723f0b3e1a0d2948960244f9721d1646 (diff)
openvswitch: kernel datapath clone action
Add 'clone' action to kernel datapath by using existing functions. When actions within clone don't modify the current flow, the flow key is not cloned before executing clone actions. This is a follow up patch for this incomplete work: https://patchwork.ozlabs.org/patch/722096/ v1 -> v2: Refactor as advised by reviewer. Signed-off-by: Yifeng Sun <pkusunyifeng@gmail.com> Signed-off-by: Andy Zhou <azhou@ovn.org> Acked-by: Pravin B Shelar <pshelar@ovn.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/actions.c33
-rw-r--r--net/openvswitch/flow_netlink.c73
2 files changed, 106 insertions, 0 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 30a5df27116e..85ae53d8fd09 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -1057,6 +1057,28 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
1057 clone_flow_key); 1057 clone_flow_key);
1058} 1058}
1059 1059
1060/* When 'last' is true, clone() should always consume the 'skb'.
1061 * Otherwise, clone() should keep 'skb' intact regardless what
1062 * actions are executed within clone().
1063 */
1064static int clone(struct datapath *dp, struct sk_buff *skb,
1065 struct sw_flow_key *key, const struct nlattr *attr,
1066 bool last)
1067{
1068 struct nlattr *actions;
1069 struct nlattr *clone_arg;
1070 int rem = nla_len(attr);
1071 bool dont_clone_flow_key;
1072
1073 /* The first action is always 'OVS_CLONE_ATTR_ARG'. */
1074 clone_arg = nla_data(attr);
1075 dont_clone_flow_key = nla_get_u32(clone_arg);
1076 actions = nla_next(clone_arg, &rem);
1077
1078 return clone_execute(dp, skb, key, 0, actions, rem, last,
1079 !dont_clone_flow_key);
1080}
1081
1060static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key, 1082static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key,
1061 const struct nlattr *attr) 1083 const struct nlattr *attr)
1062{ 1084{
@@ -1336,6 +1358,17 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
1336 consume_skb(skb); 1358 consume_skb(skb);
1337 return 0; 1359 return 0;
1338 } 1360 }
1361 break;
1362
1363 case OVS_ACTION_ATTR_CLONE: {
1364 bool last = nla_is_last(a, rem);
1365
1366 err = clone(dp, skb, key, a, last);
1367 if (last)
1368 return err;
1369
1370 break;
1371 }
1339 } 1372 }
1340 1373
1341 if (unlikely(err)) { 1374 if (unlikely(err)) {
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 391c4073a6dc..a70097ecf33c 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -2460,6 +2460,40 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr,
2460 return 0; 2460 return 0;
2461} 2461}
2462 2462
2463static int validate_and_copy_clone(struct net *net,
2464 const struct nlattr *attr,
2465 const struct sw_flow_key *key,
2466 struct sw_flow_actions **sfa,
2467 __be16 eth_type, __be16 vlan_tci,
2468 bool log, bool last)
2469{
2470 int start, err;
2471 u32 exec;
2472
2473 if (nla_len(attr) && nla_len(attr) < NLA_HDRLEN)
2474 return -EINVAL;
2475
2476 start = add_nested_action_start(sfa, OVS_ACTION_ATTR_CLONE, log);
2477 if (start < 0)
2478 return start;
2479
2480 exec = last || !actions_may_change_flow(attr);
2481
2482 err = ovs_nla_add_action(sfa, OVS_CLONE_ATTR_EXEC, &exec,
2483 sizeof(exec), log);
2484 if (err)
2485 return err;
2486
2487 err = __ovs_nla_copy_actions(net, attr, key, sfa,
2488 eth_type, vlan_tci, log);
2489 if (err)
2490 return err;
2491
2492 add_nested_action_end(*sfa, start);
2493
2494 return 0;
2495}
2496
2463void ovs_match_init(struct sw_flow_match *match, 2497void ovs_match_init(struct sw_flow_match *match,
2464 struct sw_flow_key *key, 2498 struct sw_flow_key *key,
2465 bool reset_key, 2499 bool reset_key,
@@ -2849,6 +2883,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
2849 [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1, 2883 [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
2850 [OVS_ACTION_ATTR_POP_NSH] = 0, 2884 [OVS_ACTION_ATTR_POP_NSH] = 0,
2851 [OVS_ACTION_ATTR_METER] = sizeof(u32), 2885 [OVS_ACTION_ATTR_METER] = sizeof(u32),
2886 [OVS_ACTION_ATTR_CLONE] = (u32)-1,
2852 }; 2887 };
2853 const struct ovs_action_push_vlan *vlan; 2888 const struct ovs_action_push_vlan *vlan;
2854 int type = nla_type(a); 2889 int type = nla_type(a);
@@ -3038,6 +3073,18 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
3038 /* Non-existent meters are simply ignored. */ 3073 /* Non-existent meters are simply ignored. */
3039 break; 3074 break;
3040 3075
3076 case OVS_ACTION_ATTR_CLONE: {
3077 bool last = nla_is_last(a, rem);
3078
3079 err = validate_and_copy_clone(net, a, key, sfa,
3080 eth_type, vlan_tci,
3081 log, last);
3082 if (err)
3083 return err;
3084 skip_copy = true;
3085 break;
3086 }
3087
3041 default: 3088 default:
3042 OVS_NLERR(log, "Unknown Action type %d", type); 3089 OVS_NLERR(log, "Unknown Action type %d", type);
3043 return -EINVAL; 3090 return -EINVAL;
@@ -3116,6 +3163,26 @@ out:
3116 return err; 3163 return err;
3117} 3164}
3118 3165
3166static int clone_action_to_attr(const struct nlattr *attr,
3167 struct sk_buff *skb)
3168{
3169 struct nlattr *start;
3170 int err = 0, rem = nla_len(attr);
3171
3172 start = nla_nest_start(skb, OVS_ACTION_ATTR_CLONE);
3173 if (!start)
3174 return -EMSGSIZE;
3175
3176 err = ovs_nla_put_actions(nla_data(attr), rem, skb);
3177
3178 if (err)
3179 nla_nest_cancel(skb, start);
3180 else
3181 nla_nest_end(skb, start);
3182
3183 return err;
3184}
3185
3119static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) 3186static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
3120{ 3187{
3121 const struct nlattr *ovs_key = nla_data(a); 3188 const struct nlattr *ovs_key = nla_data(a);
@@ -3204,6 +3271,12 @@ int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb)
3204 return err; 3271 return err;
3205 break; 3272 break;
3206 3273
3274 case OVS_ACTION_ATTR_CLONE:
3275 err = clone_action_to_attr(a, skb);
3276 if (err)
3277 return err;
3278 break;
3279
3207 default: 3280 default:
3208 if (nla_put(skb, type, nla_len(a), nla_data(a))) 3281 if (nla_put(skb, type, nla_len(a), nla_data(a)))
3209 return -EMSGSIZE; 3282 return -EMSGSIZE;