OVS datapath flows aren't overlapping, so having their tc flower counterparts be prioritized makes no sense, we did so because of a tc flower restriction.
Kernel tc flower added support for multiple masks on a single flower instance (there's an instance per priority) to remove this restriction. Probe for this once on first added port, and if available, use a single priority per ethertype when inserting tc flower flows. Signed-off-by: Paul Blakey <pa...@mellanox.com> Reviewed-by: Roi Dayan <r...@mellanox.com> --- lib/netdev-tc-offloads.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---- tests/ofproto-macros.at | 1 + 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c index 101b2ff..7bac62a 100644 --- a/lib/netdev-tc-offloads.c +++ b/lib/netdev-tc-offloads.c @@ -43,6 +43,7 @@ VLOG_DEFINE_THIS_MODULE(netdev_tc_offloads); static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5); static struct hmap ufid_tc = HMAP_INITIALIZER(&ufid_tc); +static bool multi_mask_per_prio = false; struct netlink_field { int offset; @@ -264,17 +265,21 @@ get_prio_for_tc_flower(struct tc_flower *flower) static struct ovs_mutex prios_lock = OVS_MUTEX_INITIALIZER; static uint16_t last_prio = 0; size_t key_len = sizeof(struct tc_flower_key); - size_t hash = hash_bytes(&flower->mask, key_len, - (OVS_FORCE uint32_t) flower->key.eth_type); + size_t hash = hash_int((OVS_FORCE uint32_t) flower->key.eth_type, 0); struct prio_map_data *data; struct prio_map_data *new_data; + if (!multi_mask_per_prio) { + hash = hash_bytes(&flower->mask, key_len, hash); + } + /* We can use the same prio for same mask/eth combination but must have * different prio if not. Flower classifier will reject same prio for - * different mask/eth combination. */ + * different mask combination unless multi mask per prio is supported. */ ovs_mutex_lock(&prios_lock); HMAP_FOR_EACH_WITH_HASH(data, node, hash, &prios) { - if (!memcmp(&flower->mask, &data->mask, key_len) + if ((multi_mask_per_prio + || !memcmp(&flower->mask, &data->mask, key_len)) && data->protocol == flower->key.eth_type) { ovs_mutex_unlock(&prios_lock); return data->prio; @@ -1199,9 +1204,44 @@ netdev_tc_flow_del(struct netdev *netdev OVS_UNUSED, return error; } +static void +probe_multi_mask_per_prio(int ifindex) +{ + struct tc_flower flower; + int error; + + memset(&flower, 0, sizeof flower); + + flower.key.eth_type = htons(ETH_P_IP); + flower.mask.eth_type = 0xfff; + memset(&flower.key.dst_mac, 0x11, sizeof flower.key.dst_mac); + memset(&flower.mask.dst_mac, 0xff, sizeof flower.mask.dst_mac); + + error = tc_replace_flower(ifindex, 1, 1, &flower); + if (error) { + return; + } + + memset(&flower.key.src_mac, 0x11, sizeof flower.key.src_mac); + memset(&flower.mask.src_mac, 0xff, sizeof flower.mask.src_mac); + + error = tc_replace_flower(ifindex, 1, 2, &flower); + tc_del_filter(ifindex, 1, 1); + + if (error) { + return; + } + + tc_del_filter(ifindex, 1, 2); + + multi_mask_per_prio = true; + VLOG_INFO("probe tc: multiple masks on single tc prio is supported."); +} + int netdev_tc_init_flow_api(struct netdev *netdev) { + static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; int ifindex; int error; @@ -1222,5 +1262,10 @@ netdev_tc_init_flow_api(struct netdev *netdev) VLOG_INFO("added ingress qdisc to %s", netdev_get_name(netdev)); + if (ovsthread_once_start(&once)) { + probe_multi_mask_per_prio(ifindex); + ovsthread_once_done(&once); + } + return 0; } diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at index c2dbec2..9a37464 100644 --- a/tests/ofproto-macros.at +++ b/tests/ofproto-macros.at @@ -346,6 +346,7 @@ m4_define([_OVS_VSWITCHD_START], /dpdk|INFO|DPDK Disabled - Use other_config:dpdk-init to enable/d /netlink_socket|INFO|netlink: could not enable listening to all nsid/d /netdev: Flow API/d +/probe tc:/d /tc: Using policy/d']]) ]) -- 2.7.4 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev