aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorPaul Blakey <paulb@mellanox.com>2019-09-04 09:56:37 -0400
committerDavid S. Miller <davem@davemloft.net>2019-09-06 08:59:18 -0400
commit95a7233c452a58a4c2310c456c73997853b2ec46 (patch)
tree5bb8386f508373060f22f1975039cd87cea2beb2 /net/openvswitch
parent47e25277693c566c47678ac3ea1929a854071e09 (diff)
net: openvswitch: Set OvS recirc_id from tc chain index
Offloaded OvS datapath rules are translated one to one to tc rules, for example the following simplified OvS rule: recirc_id(0),in_port(dev1),eth_type(0x0800),ct_state(-trk) actions:ct(),recirc(2) Will be translated to the following tc rule: $ tc filter add dev dev1 ingress \ prio 1 chain 0 proto ip \ flower tcp ct_state -trk \ action ct pipe \ action goto chain 2 Received packets will first travel though tc, and if they aren't stolen by it, like in the above rule, they will continue to OvS datapath. Since we already did some actions (action ct in this case) which might modify the packets, and updated action stats, we would like to continue the proccessing with the correct recirc_id in OvS (here recirc_id(2)) where we left off. To support this, introduce a new skb extension for tc, which will be used for translating tc chain to ovs recirc_id to handle these miss cases. Last tc chain index will be set by tc goto chain action and read by OvS datapath. Signed-off-by: Paul Blakey <paulb@mellanox.com> Signed-off-by: Vlad Buslov <vladbu@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com> 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/datapath.c38
-rw-r--r--net/openvswitch/datapath.h2
-rw-r--r--net/openvswitch/flow.c13
3 files changed, 48 insertions, 5 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 65122bbccd27..dde9d762edee 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1545,10 +1545,34 @@ static void ovs_dp_reset_user_features(struct sk_buff *skb, struct genl_info *in
1545 dp->user_features = 0; 1545 dp->user_features = 0;
1546} 1546}
1547 1547
1548static void ovs_dp_change(struct datapath *dp, struct nlattr *a[]) 1548DEFINE_STATIC_KEY_FALSE(tc_recirc_sharing_support);
1549
1550static int ovs_dp_change(struct datapath *dp, struct nlattr *a[])
1549{ 1551{
1550 if (a[OVS_DP_ATTR_USER_FEATURES]) 1552 u32 user_features = 0;
1551 dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]); 1553
1554 if (a[OVS_DP_ATTR_USER_FEATURES]) {
1555 user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]);
1556
1557 if (user_features & ~(OVS_DP_F_VPORT_PIDS |
1558 OVS_DP_F_UNALIGNED |
1559 OVS_DP_F_TC_RECIRC_SHARING))
1560 return -EOPNOTSUPP;
1561
1562#if !IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
1563 if (user_features & OVS_DP_F_TC_RECIRC_SHARING)
1564 return -EOPNOTSUPP;
1565#endif
1566 }
1567
1568 dp->user_features = user_features;
1569
1570 if (dp->user_features & OVS_DP_F_TC_RECIRC_SHARING)
1571 static_branch_enable(&tc_recirc_sharing_support);
1572 else
1573 static_branch_disable(&tc_recirc_sharing_support);
1574
1575 return 0;
1552} 1576}
1553 1577
1554static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) 1578static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
@@ -1610,7 +1634,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1610 parms.port_no = OVSP_LOCAL; 1634 parms.port_no = OVSP_LOCAL;
1611 parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID]; 1635 parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
1612 1636
1613 ovs_dp_change(dp, a); 1637 err = ovs_dp_change(dp, a);
1638 if (err)
1639 goto err_destroy_meters;
1614 1640
1615 /* So far only local changes have been made, now need the lock. */ 1641 /* So far only local changes have been made, now need the lock. */
1616 ovs_lock(); 1642 ovs_lock();
@@ -1736,7 +1762,9 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
1736 if (IS_ERR(dp)) 1762 if (IS_ERR(dp))
1737 goto err_unlock_free; 1763 goto err_unlock_free;
1738 1764
1739 ovs_dp_change(dp, info->attrs); 1765 err = ovs_dp_change(dp, info->attrs);
1766 if (err)
1767 goto err_unlock_free;
1740 1768
1741 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid, 1769 err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
1742 info->snd_seq, 0, OVS_DP_CMD_SET); 1770 info->snd_seq, 0, OVS_DP_CMD_SET);
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 751d34accdf9..81e85dde8217 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -218,6 +218,8 @@ static inline struct datapath *get_dp(struct net *net, int dp_ifindex)
218extern struct notifier_block ovs_dp_device_notifier; 218extern struct notifier_block ovs_dp_device_notifier;
219extern struct genl_family dp_vport_genl_family; 219extern struct genl_family dp_vport_genl_family;
220 220
221DECLARE_STATIC_KEY_FALSE(tc_recirc_sharing_support);
222
221void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key); 223void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key);
222void ovs_dp_detach_port(struct vport *); 224void ovs_dp_detach_port(struct vport *);
223int ovs_dp_upcall(struct datapath *, struct sk_buff *, 225int ovs_dp_upcall(struct datapath *, struct sk_buff *,
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d81d2c7bf82..38147e6a20f5 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -842,6 +842,9 @@ static int key_extract_mac_proto(struct sk_buff *skb)
842int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, 842int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
843 struct sk_buff *skb, struct sw_flow_key *key) 843 struct sk_buff *skb, struct sw_flow_key *key)
844{ 844{
845#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
846 struct tc_skb_ext *tc_ext;
847#endif
845 int res, err; 848 int res, err;
846 849
847 /* Extract metadata from packet. */ 850 /* Extract metadata from packet. */
@@ -874,7 +877,17 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
874 if (res < 0) 877 if (res < 0)
875 return res; 878 return res;
876 key->mac_proto = res; 879 key->mac_proto = res;
880
881#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
882 if (static_branch_unlikely(&tc_recirc_sharing_support)) {
883 tc_ext = skb_ext_find(skb, TC_SKB_EXT);
884 key->recirc_id = tc_ext ? tc_ext->chain : 0;
885 } else {
886 key->recirc_id = 0;
887 }
888#else
877 key->recirc_id = 0; 889 key->recirc_id = 0;
890#endif
878 891
879 err = key_extract(skb, key); 892 err = key_extract(skb, key);
880 if (!err) 893 if (!err)