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
2121
2222 #include <uapi/linux/openvswitch.h>
2323
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+
2429 #endif /* _LINUX_OPENVSWITCH_H */
include/uapi/linux/openvswitch.h+3−0
@@ -840,6 +840,8 @@ struct ovs_action_push_eth { · 839 unmodified lines
840840 * @OVS_ACTION_ATTR_POP_NSH: pop the outermost NSH header off the packet.
841841 * @OVS_ACTION_ATTR_METER: Run packet through a meter, which may drop the
842842 * 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.
843845 *
844846 * Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
845847 * fields within a header are modifiable, e.g. the IPv4 protocol and fragment
@@ -873,6 +875,7 @@ enum ovs_action_attr { · 27 unmodified lines
873875 OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */
874876 OVS_ACTION_ATTR_POP_NSH, /* No argument. */
875877 OVS_ACTION_ATTR_METER, /* u32 meter ID. */
878+ OVS_ACTION_ATTR_CLONE, /* Nested OVS_CLONE_ATTR_*. */
876879
877880 __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
878881 * 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
10571057 clone_flow_key);
10581058 }
10591059
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+ */
1064+static 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+
10601082 static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key,
10611083 const struct nlattr *attr)
10621084 {
@@ -1336,6 +1358,17 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, · 273 unmodified lines
13361358 consume_skb(skb);
13371359 return 0;
13381360 }
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+ }
13391372 }
13401373
13411374 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
24602460 return 0;
24612461 }
24622462
2463+static 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+
24632497 void ovs_match_init(struct sw_flow_match *match,
24642498 struct sw_flow_key *key,
24652499 bool reset_key,
@@ -2849,6 +2883,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr, · 383 unmodified lines
28492883 [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
28502884 [OVS_ACTION_ATTR_POP_NSH] = 0,
28512885 [OVS_ACTION_ATTR_METER] = sizeof(u32),
2886+ [OVS_ACTION_ATTR_CLONE] = (u32)-1,
28522887 };
28532888 const struct ovs_action_push_vlan *vlan;
28542889 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
30383073 /* Non-existent meters are simply ignored. */
30393074 break;
30403075
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+
30413088 default:
30423089 OVS_NLERR(log, "Unknown Action type %d", type);
30433090 return -EINVAL;
@@ -3116,6 +3163,26 @@ out: · 72 unmodified lines
31163163 return err;
31173164 }
31183165
3166+static 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+
31193186 static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
31203187 {
31213188 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
32043271 return err;
32053272 break;
32063273
3274+ case OVS_ACTION_ATTR_CLONE:
3275+ err = clone_action_to_attr(a, skb);
3276+ if (err)
3277+ return err;
3278+ break;
3279+
32073280 default:
32083281 if (nla_put(skb, type, nla_len(a), nla_data(a)))
32093282 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