History

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.

Yifeng Sun committed 8 years ago

Commit b2335041 parent 20fbdc34 files · +114 −0Browse files

Unified · Split

4 files
  1. include/linux/openvswitch.h +5 −0
  2. include/uapi/linux/openvswitch.h +3 −0
  3. net/openvswitch/actions.c +33 −0
  4. net/openvswitch/flow_netlink.c +73 −0
include/linux/openvswitch.h+5−0
@@ -21,4 +21,9 @@ · 20 unmodified lines
21 21
22#include <uapi/linux/openvswitch.h>22#include <uapi/linux/openvswitch.h>
23 23
24#define OVS_CLONE_ATTR_EXEC 0 /* Specify an u32 value. When nonzero,
25 * actions in clone will not change flow
26 * keys. False otherwise.
27 */
28
24#endif /* _LINUX_OPENVSWITCH_H */29#endif /* _LINUX_OPENVSWITCH_H */
include/uapi/linux/openvswitch.h+3−0
@@ -840,6 +840,8 @@ struct ovs_action_push_eth { · 839 unmodified lines
840 * @OVS_ACTION_ATTR_POP_NSH: pop the outermost NSH header off the packet.840 * @OVS_ACTION_ATTR_POP_NSH: pop the outermost NSH header off the packet.
841 * @OVS_ACTION_ATTR_METER: Run packet through a meter, which may drop the841 * @OVS_ACTION_ATTR_METER: Run packet through a meter, which may drop the
842 * packet, or modify the packet (e.g., change the DSCP field).842 * packet, or modify the packet (e.g., change the DSCP field).
843 * @OVS_ACTION_ATTR_CLONE: make a copy of the packet and execute a list of
844 * actions without affecting the original packet and key.
843 *845 *
844 * Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all846 * Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
845 * fields within a header are modifiable, e.g. the IPv4 protocol and fragment847 * fields within a header are modifiable, e.g. the IPv4 protocol and fragment
@@ -873,6 +875,7 @@ enum ovs_action_attr { · 27 unmodified lines
873 OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */875 OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */
874 OVS_ACTION_ATTR_POP_NSH, /* No argument. */876 OVS_ACTION_ATTR_POP_NSH, /* No argument. */
875 OVS_ACTION_ATTR_METER, /* u32 meter ID. */877 OVS_ACTION_ATTR_METER, /* u32 meter ID. */
878 OVS_ACTION_ATTR_CLONE, /* Nested OVS_CLONE_ATTR_*. */
876 879
877 __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted880 __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
878 * from userspace. */881 * from userspace. */
net/openvswitch/actions.c+33−0
@@ -1057,6 +1057,28 @@ static int sample(struct datapath *dp, struct sk_buff *skb, · 1056 unmodified lines
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, · 273 unmodified lines
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)) {
net/openvswitch/flow_netlink.c+73−0
@@ -2460,6 +2460,40 @@ static int validate_and_copy_sample(struct net *net, const struct nlattr *attr, · 2459 unmodified lines
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, · 383 unmodified lines
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, · 183 unmodified lines
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: · 72 unmodified lines
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) · 82 unmodified lines
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;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t