From patchwork Tue Apr 9 14:36:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Hurley X-Patchwork-Id: 1082333 X-Patchwork-Delegate: horms@verge.net.au Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=netronome.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b="Ha+ttObx"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44dqfF31rgz9sSJ for ; Wed, 10 Apr 2019 00:38:29 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 6168E1090; Tue, 9 Apr 2019 14:36:31 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8FAFB108B for ; Tue, 9 Apr 2019 14:36:29 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-ed1-f68.google.com (mail-ed1-f68.google.com [209.85.208.68]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 0F993735 for ; Tue, 9 Apr 2019 14:36:27 +0000 (UTC) Received: by mail-ed1-f68.google.com with SMTP id b8so1667244edq.0 for ; Tue, 09 Apr 2019 07:36:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netronome-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Rdv5Jo4N5tPBpdSLrepzxMMBrHjmUrmHdufrIlA0Yrk=; b=Ha+ttObxAEpOA4HmGUocnDJsjJXX3BLlPc3Ge6SXpYyo9cGndrhcartWDpWoTGnmfE hd9douXPrW5GBHr+wlf8sTw4cYBOLqcCyL8B3vwkaDtJq+GD8gY9Fo4jGg30xBoJa0cv SPMyR7AUkd9z+bfKyQbF0Ma2osMBAXup8JQTlVLKUml9BUT9rAAUy6NwEEul3pyvUv0o WMj8tXzF6gBfQ3/eFgshVkmtpu9IzEyNVR15vGrWCDWtP0ZLmR9QFnFQE25pBhltKVGw OvB2jW9/CQgKg1MIYYNP6rnCPzWA7DdX/J9zET15HVE88lgpsUc32FbvrIZiVjTDdTIy 9TUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Rdv5Jo4N5tPBpdSLrepzxMMBrHjmUrmHdufrIlA0Yrk=; b=clMQsGuES4oWCKNhQu5QINnI7Lz0gta3NunYKMsSVbck5pBOoUcPma/9cbqqZV2oux 3rIegGqYlUJFy7XGFeurWOiNp5o0BrjZzgYO5U0b4ITDYm0wYIyTGuMvo3Sd/u2YJc8L 4ZjTE9D5l6Ppeluv1bXXj03uSMTpKpKh/z3GubFwwuP/vbND/yCDMbX/9lIeROu4LJrZ qrvGVXpWH5f0Mree8Qkc3I3h31CtfIsrDq0r8tDZBF+lciiwRIRM8ARUm8xE6ipVciJ0 0KMlAsDfHlBYZ9b4784TJegk5G2fh1gljXh3WPtrWYpAwEYDmeebdZCSNJvK2HjP/Tqz 4rLg== X-Gm-Message-State: APjAAAXDEb7LP7WaNLMqDHDc4y1ruYJz5P8hvsIQUdljqkYmqYZyldXh gYXmSAgKHAxzXbQaNBlZ+jqVMaBwiBI= X-Google-Smtp-Source: APXvYqz83VLLA/4y/AIH3S14tvErKW0Cm0/KxNWrLKOr0/kbLoG00YaHEtuOft2SQMTUxwgnrSZJJA== X-Received: by 2002:a17:906:2969:: with SMTP id x9mr20115219ejd.223.1554820586087; Tue, 09 Apr 2019 07:36:26 -0700 (PDT) Received: from jhurley-Precision-Tower-3420.netronome.com ([80.76.204.157]) by smtp.gmail.com with ESMTPSA id j3sm6044567ejv.22.2019.04.09.07.36.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 09 Apr 2019 07:36:25 -0700 (PDT) From: John Hurley To: dev@openvswitch.org, roid@mellanox.com, fbl@sysclose.org, simon.horman@netronome.com Date: Tue, 9 Apr 2019 15:36:13 +0100 Message-Id: <1554820574-22848-4-git-send-email-john.hurley@netronome.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1554820574-22848-1-git-send-email-john.hurley@netronome.com> References: <1554820574-22848-1-git-send-email-john.hurley@netronome.com> X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: oss-drivers@netronome.com Subject: [ovs-dev] [PATCH OVS v3 3/4] ovs-tc: allow offloading TC rules to egress qdiscs X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Offloading rules to a TC datapath only allows the creating of ingress hook qdiscs and the application of filters to these. However, there may be certain situations where an egress qdisc is more applicable (e.g. when offloading to TC rules applied to OvS internal ports). Extend the TC API in OvS to allow the creation of egress qdiscs and to add or interact with flower filters applied to these. Signed-off-by: John Hurley Reviewed-by: Simon Horman Reviewed-by: Roi Dayan --- lib/netdev-linux.c | 17 +++++++------- lib/netdev-tc-offloads.c | 36 ++++++++++++++++-------------- lib/tc.c | 58 ++++++++++++++++++++++++++++++++++-------------- lib/tc.h | 26 +++++++++++++++++----- 4 files changed, 89 insertions(+), 48 deletions(-) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index deedc69..87337e0 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -747,10 +747,10 @@ netdev_linux_update_lag(struct rtnetlink_change *change) lag->node = shash_add(&lag_shash, change->ifname, lag); /* delete ingress block in case it exists */ - tc_add_del_ingress_qdisc(change->if_index, false, 0); + tc_add_del_qdisc(change->if_index, false, 0, TC_INGRESS); /* LAG master is linux netdev so add slave to same block. */ - error = tc_add_del_ingress_qdisc(change->if_index, true, - block_id); + error = tc_add_del_qdisc(change->if_index, true, block_id, + TC_INGRESS); if (error) { VLOG_WARN("failed to bind LAG slave %s to master's block", change->ifname); @@ -766,8 +766,8 @@ netdev_linux_update_lag(struct rtnetlink_change *change) lag = shash_find_data(&lag_shash, change->ifname); if (lag) { - tc_add_del_ingress_qdisc(change->if_index, false, - lag->block_id); + tc_add_del_qdisc(change->if_index, false, lag->block_id, + TC_INGRESS); shash_delete(&lag_shash, lag->node); free(lag); } @@ -2430,7 +2430,8 @@ tc_del_matchall_policer(struct netdev *netdev) return err; } - err = tc_del_filter(ifindex, TC_RESERVED_PRIORITY_POLICE, 1, block_id); + err = tc_del_filter(ifindex, TC_RESERVED_PRIORITY_POLICE, 1, block_id, + TC_INGRESS); if (err) { return err; } @@ -2486,7 +2487,7 @@ netdev_linux_set_policing(struct netdev *netdev_, COVERAGE_INC(netdev_set_policing); /* Remove any existing ingress qdisc. */ - error = tc_add_del_ingress_qdisc(ifindex, false, 0); + error = tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS); if (error) { VLOG_WARN_RL(&rl, "%s: removing policing failed: %s", netdev_name, ovs_strerror(error)); @@ -2494,7 +2495,7 @@ netdev_linux_set_policing(struct netdev *netdev_, } if (kbits_rate) { - error = tc_add_del_ingress_qdisc(ifindex, true, 0); + error = tc_add_del_qdisc(ifindex, true, 0, TC_INGRESS); if (error) { VLOG_WARN_RL(&rl, "%s: adding policing qdisc failed: %s", netdev_name, ovs_strerror(error)); diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c index c18992d..634c9b9 100644 --- a/lib/netdev-tc-offloads.c +++ b/lib/netdev-tc-offloads.c @@ -189,7 +189,7 @@ del_filter_and_ufid_mapping(int ifindex, int prio, int handle, { int err; - err = tc_del_filter(ifindex, prio, handle, block_id); + err = tc_del_filter(ifindex, prio, handle, block_id, TC_INGRESS); del_ufid_tc_mapping(ufid); return err; @@ -357,7 +357,7 @@ netdev_tc_flow_flush(struct netdev *netdev) block_id = get_block_id_from_netdev(netdev); - return tc_flush(ifindex, block_id); + return tc_flush(ifindex, block_id, TC_INGRESS); } int @@ -379,7 +379,7 @@ netdev_tc_flow_dump_create(struct netdev *netdev, dump = xzalloc(sizeof *dump); dump->nl_dump = xzalloc(sizeof *dump->nl_dump); dump->netdev = netdev_ref(netdev); - tc_dump_flower_start(ifindex, dump->nl_dump, block_id); + tc_dump_flower_start(ifindex, dump->nl_dump, block_id, TC_INGRESS); *dump_out = dump; @@ -1356,7 +1356,8 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, flower.act_cookie.data = ufid; flower.act_cookie.len = sizeof *ufid; - err = tc_replace_flower(ifindex, prio, handle, &flower, block_id); + err = tc_replace_flower(ifindex, prio, handle, &flower, block_id, + TC_INGRESS); if (!err) { add_ufid_tc_mapping(ufid, flower.prio, flower.handle, netdev, ifindex); } @@ -1399,7 +1400,7 @@ netdev_tc_flow_get(struct netdev *netdev OVS_UNUSED, block_id = get_block_id_from_netdev(dev); VLOG_DBG_RL(&rl, "flow get (dev %s prio %d handle %d block_id %d)", netdev_get_name(dev), prio, handle, block_id); - err = tc_get_flower(ifindex, prio, handle, &flower, block_id); + err = tc_get_flower(ifindex, prio, handle, &flower, block_id, TC_INGRESS); netdev_close(dev); if (err) { VLOG_ERR_RL(&error_rl, "flow get failed (dev %s prio %d handle %d): %s", @@ -1446,7 +1447,8 @@ netdev_tc_flow_del(struct netdev *netdev OVS_UNUSED, if (stats) { memset(stats, 0, sizeof *stats); - if (!tc_get_flower(ifindex, prio, handle, &flower, block_id)) { + if (!tc_get_flower(ifindex, prio, handle, &flower, block_id, + TC_INGRESS)) { stats->n_packets = get_32aligned_u64(&flower.stats.n_packets); stats->n_bytes = get_32aligned_u64(&flower.stats.n_bytes); stats->used = flower.lastused; @@ -1467,7 +1469,7 @@ probe_multi_mask_per_prio(int ifindex) int block_id = 0; int error; - error = tc_add_del_ingress_qdisc(ifindex, true, block_id); + error = tc_add_del_qdisc(ifindex, true, block_id, TC_INGRESS); if (error) { return; } @@ -1479,7 +1481,7 @@ probe_multi_mask_per_prio(int ifindex) 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, block_id); + error = tc_replace_flower(ifindex, 1, 1, &flower, block_id, TC_INGRESS); if (error) { goto out; } @@ -1487,20 +1489,20 @@ probe_multi_mask_per_prio(int ifindex) 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, block_id); - tc_del_filter(ifindex, 1, 1, block_id); + error = tc_replace_flower(ifindex, 1, 2, &flower, block_id, TC_INGRESS); + tc_del_filter(ifindex, 1, 1, block_id, TC_INGRESS); if (error) { goto out; } - tc_del_filter(ifindex, 1, 2, block_id); + tc_del_filter(ifindex, 1, 2, block_id, TC_INGRESS); multi_mask_per_prio = true; VLOG_INFO("probe tc: multiple masks on single tc prio is supported."); out: - tc_add_del_ingress_qdisc(ifindex, false, block_id); + tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS); } static void @@ -1510,7 +1512,7 @@ probe_tc_block_support(int ifindex) uint32_t block_id = 1; int error; - error = tc_add_del_ingress_qdisc(ifindex, true, block_id); + error = tc_add_del_qdisc(ifindex, true, block_id, TC_INGRESS); if (error) { return; } @@ -1522,9 +1524,9 @@ probe_tc_block_support(int ifindex) 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, block_id); + error = tc_replace_flower(ifindex, 1, 1, &flower, block_id, TC_INGRESS); - tc_add_del_ingress_qdisc(ifindex, false, block_id); + tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS); if (!error) { block_support = true; @@ -1549,7 +1551,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) } /* make sure there is no ingress qdisc */ - tc_add_del_ingress_qdisc(ifindex, false, 0); + tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS); if (ovsthread_once_start(&block_once)) { probe_tc_block_support(ifindex); @@ -1562,7 +1564,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) } block_id = get_block_id_from_netdev(netdev); - error = tc_add_del_ingress_qdisc(ifindex, true, block_id); + error = tc_add_del_qdisc(ifindex, true, block_id, TC_INGRESS); if (error && error != EEXIST) { VLOG_ERR("failed adding ingress qdisc required for offloading: %s", diff --git a/lib/tc.c b/lib/tc.c index 336cdeb..1eca356 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -201,14 +201,21 @@ tc_transact(struct ofpbuf *request, struct ofpbuf **replyp) return error; } -/* Adds or deletes a root ingress qdisc on device with specified ifindex. +/* Adds or deletes a root qdisc on device with specified ifindex. * - * This function is equivalent to running the following when 'add' is true: + * The tc_qdisc_hook parameter determines if the qdisc is added on device + * ingress or egress. + * + * If tc_qdisc_hook is TC_INGRESS, this function is equivalent to running the + * following when 'add' is true: * /sbin/tc qdisc add dev handle ffff: ingress * * This function is equivalent to running the following when 'add' is false: * /sbin/tc qdisc del dev handle ffff: ingress * + * If tc_qdisc_hook is TC_EGRESS, this function is equivalent to: + * /sbin/tc qdisc (add|del) dev handle ffff: clsact + * * Where dev is the device with specified ifindex name. * * The configuration and stats may be seen with the following command: @@ -221,7 +228,8 @@ tc_transact(struct ofpbuf *request, struct ofpbuf **replyp) * Returns 0 if successful, otherwise a positive errno value. */ int -tc_add_del_ingress_qdisc(int ifindex, bool add, uint32_t block_id) +tc_add_del_qdisc(int ifindex, bool add, uint32_t block_id, + enum tc_qdisc_hook hook) { struct ofpbuf request; struct tcmsg *tcmsg; @@ -230,11 +238,19 @@ tc_add_del_ingress_qdisc(int ifindex, bool add, uint32_t block_id) int flags = add ? NLM_F_EXCL | NLM_F_CREATE : 0; tcmsg = tc_make_request(ifindex, type, flags, &request); - tcmsg->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0); - tcmsg->tcm_parent = TC_H_INGRESS; - nl_msg_put_string(&request, TCA_KIND, "ingress"); + + if (hook == TC_EGRESS) { + tcmsg->tcm_handle = TC_H_MAKE(TC_H_CLSACT, 0); + tcmsg->tcm_parent = TC_H_CLSACT; + nl_msg_put_string(&request, TCA_KIND, "clsact"); + } else { + tcmsg->tcm_handle = TC_H_MAKE(TC_H_INGRESS, 0); + tcmsg->tcm_parent = TC_H_INGRESS; + nl_msg_put_string(&request, TCA_KIND, "ingress"); + } + nl_msg_put_unspec(&request, TCA_OPTIONS, NULL, 0); - if (block_id) { + if (hook == TC_INGRESS && block_id) { nl_msg_put_u32(&request, TCA_INGRESS_BLOCK, block_id); } @@ -1455,7 +1471,8 @@ parse_netlink_to_tc_flower(struct ofpbuf *reply, struct tc_flower *flower) } int -tc_dump_flower_start(int ifindex, struct nl_dump *dump, uint32_t block_id) +tc_dump_flower_start(int ifindex, struct nl_dump *dump, uint32_t block_id, + enum tc_qdisc_hook hook) { struct ofpbuf request; struct tcmsg *tcmsg; @@ -1463,7 +1480,8 @@ tc_dump_flower_start(int ifindex, struct nl_dump *dump, uint32_t block_id) index = block_id ? TCM_IFINDEX_MAGIC_BLOCK : ifindex; tcmsg = tc_make_request(index, RTM_GETTFILTER, NLM_F_DUMP, &request); - tcmsg->tcm_parent = block_id ? : TC_INGRESS_PARENT; + tcmsg->tcm_parent = (hook == TC_EGRESS) ? + TC_EGRESS_PARENT : (block_id ? : TC_INGRESS_PARENT); tcmsg->tcm_info = TC_H_UNSPEC; tcmsg->tcm_handle = 0; @@ -1474,7 +1492,7 @@ tc_dump_flower_start(int ifindex, struct nl_dump *dump, uint32_t block_id) } int -tc_flush(int ifindex, uint32_t block_id) +tc_flush(int ifindex, uint32_t block_id, enum tc_qdisc_hook hook) { struct ofpbuf request; struct tcmsg *tcmsg; @@ -1482,14 +1500,16 @@ tc_flush(int ifindex, uint32_t block_id) index = block_id ? TCM_IFINDEX_MAGIC_BLOCK : ifindex; tcmsg = tc_make_request(index, RTM_DELTFILTER, NLM_F_ACK, &request); - tcmsg->tcm_parent = block_id ? : TC_INGRESS_PARENT; + tcmsg->tcm_parent = (hook == TC_EGRESS) ? + TC_EGRESS_PARENT : (block_id ? : TC_INGRESS_PARENT); tcmsg->tcm_info = TC_H_UNSPEC; return tc_transact(&request, NULL); } int -tc_del_filter(int ifindex, int prio, int handle, uint32_t block_id) +tc_del_filter(int ifindex, int prio, int handle, uint32_t block_id, + enum tc_qdisc_hook hook) { struct ofpbuf request; struct tcmsg *tcmsg; @@ -1499,7 +1519,8 @@ tc_del_filter(int ifindex, int prio, int handle, uint32_t block_id) index = block_id ? TCM_IFINDEX_MAGIC_BLOCK : ifindex; tcmsg = tc_make_request(index, RTM_DELTFILTER, NLM_F_ECHO, &request); - tcmsg->tcm_parent = block_id ? : TC_INGRESS_PARENT; + tcmsg->tcm_parent = (hook == TC_EGRESS) ? + TC_EGRESS_PARENT : (block_id ? : TC_INGRESS_PARENT); tcmsg->tcm_info = tc_make_handle(prio, 0); tcmsg->tcm_handle = handle; @@ -1512,7 +1533,7 @@ tc_del_filter(int ifindex, int prio, int handle, uint32_t block_id) int tc_get_flower(int ifindex, int prio, int handle, struct tc_flower *flower, - uint32_t block_id) + uint32_t block_id, enum tc_qdisc_hook hook) { struct ofpbuf request; struct tcmsg *tcmsg; @@ -1522,7 +1543,8 @@ tc_get_flower(int ifindex, int prio, int handle, struct tc_flower *flower, index = block_id ? TCM_IFINDEX_MAGIC_BLOCK : ifindex; tcmsg = tc_make_request(index, RTM_GETTFILTER, NLM_F_ECHO, &request); - tcmsg->tcm_parent = block_id ? : TC_INGRESS_PARENT; + tcmsg->tcm_parent = (hook == TC_EGRESS) ? + TC_EGRESS_PARENT : (block_id ? : TC_INGRESS_PARENT); tcmsg->tcm_info = tc_make_handle(prio, 0); tcmsg->tcm_handle = handle; @@ -2279,7 +2301,8 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower) int tc_replace_flower(int ifindex, uint16_t prio, uint32_t handle, - struct tc_flower *flower, uint32_t block_id) + struct tc_flower *flower, uint32_t block_id, + enum tc_qdisc_hook hook) { struct ofpbuf request; struct tcmsg *tcmsg; @@ -2292,7 +2315,8 @@ tc_replace_flower(int ifindex, uint16_t prio, uint32_t handle, index = block_id ? TCM_IFINDEX_MAGIC_BLOCK : ifindex; tcmsg = tc_make_request(index, RTM_NEWTFILTER, NLM_F_CREATE | NLM_F_ECHO, &request); - tcmsg->tcm_parent = block_id ? : TC_INGRESS_PARENT; + tcmsg->tcm_parent = (hook == TC_EGRESS) ? + TC_EGRESS_PARENT : (block_id ? : TC_INGRESS_PARENT); tcmsg->tcm_info = tc_make_handle(prio, eth_type); tcmsg->tcm_handle = handle; diff --git a/lib/tc.h b/lib/tc.h index 154e120..2e0f5e3 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -36,8 +36,12 @@ #ifndef TC_H_MIN_INGRESS #define TC_H_MIN_INGRESS 0xFFF2U #endif +#ifndef TC_H_MIN_EGRESS +#define TC_H_MIN_EGRESS 0xFFF3U +#endif #define TC_INGRESS_PARENT TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS) +#define TC_EGRESS_PARENT TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS) #define TC_POLICY_DEFAULT "none" @@ -48,6 +52,11 @@ enum tc_flower_reserved_prio { }; #define TC_RESERVED_PRIORITY_MAX (__TC_RESERVED_PRIORITY_MAX -1) +enum tc_qdisc_hook { + TC_INGRESS, + TC_EGRESS, +}; + /* Returns tc handle 'major':'minor'. */ static inline unsigned int tc_make_handle(unsigned int major, unsigned int minor) @@ -72,7 +81,8 @@ tc_get_minor(unsigned int handle) struct tcmsg *tc_make_request(int ifindex, int type, unsigned int flags, struct ofpbuf *); int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp); -int tc_add_del_ingress_qdisc(int ifindex, bool add, uint32_t block_id); +int tc_add_del_qdisc(int ifindex, bool add, uint32_t block_id, + enum tc_qdisc_hook hook); struct tc_cookie { const void *data; @@ -225,12 +235,16 @@ BUILD_ASSERT_DECL(offsetof(struct tc_flower, rewrite) + sizeof(uint32_t) - 2 < sizeof(struct tc_flower)); int tc_replace_flower(int ifindex, uint16_t prio, uint32_t handle, - struct tc_flower *flower, uint32_t block_id); -int tc_del_filter(int ifindex, int prio, int handle, uint32_t block_id); + struct tc_flower *flower, uint32_t block_id, + enum tc_qdisc_hook hook); +int tc_del_filter(int ifindex, int prio, int handle, uint32_t block_id, + enum tc_qdisc_hook hook); int tc_get_flower(int ifindex, int prio, int handle, - struct tc_flower *flower, uint32_t block_id); -int tc_flush(int ifindex, uint32_t block_id); -int tc_dump_flower_start(int ifindex, struct nl_dump *dump, uint32_t block_id); + struct tc_flower *flower, uint32_t block_id, + enum tc_qdisc_hook hook); +int tc_flush(int ifindex, uint32_t block_id, enum tc_qdisc_hook hook); +int tc_dump_flower_start(int ifindex, struct nl_dump *dump, uint32_t block_id, + enum tc_qdisc_hook hook); int parse_netlink_to_tc_flower(struct ofpbuf *reply, struct tc_flower *flower); void tc_set_policy(const char *policy);