Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

openvswitch: add ct_clear action

This adds a ct_clear action for clearing conntrack state. ct_clear is
currently implemented in OVS userspace, but is not backed by an action
in the kernel datapath. This is useful for flows that may modify a
packet tuple after a ct lookup has already occurred.

Signed-off-by: Eric Garver <e@erig.me>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Garver and committed by
David S. Miller
b8226962 833e0e2f

+29
+2
include/uapi/linux/openvswitch.h
··· 807 807 * packet. 808 808 * @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the 809 809 * packet. 810 + * @OVS_ACTION_ATTR_CT_CLEAR: Clear conntrack state from the packet. 810 811 * 811 812 * Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all 812 813 * fields within a header are modifiable, e.g. the IPv4 protocol and fragment ··· 837 836 OVS_ACTION_ATTR_TRUNC, /* u32 struct ovs_action_trunc. */ 838 837 OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */ 839 838 OVS_ACTION_ATTR_POP_ETH, /* No argument. */ 839 + OVS_ACTION_ATTR_CT_CLEAR, /* No argument. */ 840 840 841 841 __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted 842 842 * from userspace. */
+4
net/openvswitch/actions.c
··· 1203 1203 return err == -EINPROGRESS ? 0 : err; 1204 1204 break; 1205 1205 1206 + case OVS_ACTION_ATTR_CT_CLEAR: 1207 + err = ovs_ct_clear(skb, key); 1208 + break; 1209 + 1206 1210 case OVS_ACTION_ATTR_PUSH_ETH: 1207 1211 err = push_eth(skb, key, nla_data(a)); 1208 1212 break;
+11
net/openvswitch/conntrack.c
··· 1129 1129 return err; 1130 1130 } 1131 1131 1132 + int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key) 1133 + { 1134 + if (skb_nfct(skb)) { 1135 + nf_conntrack_put(skb_nfct(skb)); 1136 + nf_ct_set(skb, NULL, IP_CT_UNTRACKED); 1137 + ovs_ct_fill_key(skb, key); 1138 + } 1139 + 1140 + return 0; 1141 + } 1142 + 1132 1143 static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name, 1133 1144 const struct sw_flow_key *key, bool log) 1134 1145 {
+7
net/openvswitch/conntrack.h
··· 30 30 31 31 int ovs_ct_execute(struct net *, struct sk_buff *, struct sw_flow_key *, 32 32 const struct ovs_conntrack_info *); 33 + int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key); 33 34 34 35 void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key); 35 36 int ovs_ct_put_key(const struct sw_flow_key *swkey, ··· 71 70 const struct ovs_conntrack_info *info) 72 71 { 73 72 kfree_skb(skb); 73 + return -ENOTSUPP; 74 + } 75 + 76 + static inline int ovs_ct_clear(struct sk_buff *skb, 77 + struct sw_flow_key *key) 78 + { 74 79 return -ENOTSUPP; 75 80 } 76 81
+5
net/openvswitch/flow_netlink.c
··· 76 76 break; 77 77 78 78 case OVS_ACTION_ATTR_CT: 79 + case OVS_ACTION_ATTR_CT_CLEAR: 79 80 case OVS_ACTION_ATTR_HASH: 80 81 case OVS_ACTION_ATTR_POP_ETH: 81 82 case OVS_ACTION_ATTR_POP_MPLS: ··· 2529 2528 [OVS_ACTION_ATTR_SAMPLE] = (u32)-1, 2530 2529 [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash), 2531 2530 [OVS_ACTION_ATTR_CT] = (u32)-1, 2531 + [OVS_ACTION_ATTR_CT_CLEAR] = 0, 2532 2532 [OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc), 2533 2533 [OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth), 2534 2534 [OVS_ACTION_ATTR_POP_ETH] = 0, ··· 2669 2667 if (err) 2670 2668 return err; 2671 2669 skip_copy = true; 2670 + break; 2671 + 2672 + case OVS_ACTION_ATTR_CT_CLEAR: 2672 2673 break; 2673 2674 2674 2675 case OVS_ACTION_ATTR_PUSH_ETH: