From: Paul Blakey <pa...@mellanox.com> Those that we want to reuse in tc.c
Signed-off-by: Paul Blakey <pa...@mellanox.com> Reviewed-by: Roi Dayan <r...@mellanox.com> --- lib/netdev-linux.c | 164 +++++++++++++---------------------------------------- lib/tc.c | 81 +++++++++++++++++++++----- lib/tc.h | 11 ++++ 3 files changed, 117 insertions(+), 139 deletions(-) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 9ff1333..085f530 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -29,8 +29,6 @@ #include <linux/types.h> #include <linux/ethtool.h> #include <linux/mii.h> -#include <linux/pkt_cls.h> -#include <linux/pkt_sched.h> #include <linux/rtnetlink.h> #include <linux/sockios.h> #include <sys/types.h> @@ -74,6 +72,7 @@ #include "unaligned.h" #include "openvswitch/vlog.h" #include "util.h" +#include "tc.h" VLOG_DEFINE_THIS_MODULE(netdev_linux); @@ -434,18 +433,14 @@ static const struct tc_ops *const tcs[] = { NULL }; -static unsigned int tc_make_handle(unsigned int major, unsigned int minor); -static unsigned int tc_get_major(unsigned int handle); -static unsigned int tc_get_minor(unsigned int handle); - static unsigned int tc_ticks_to_bytes(unsigned int rate, unsigned int ticks); static unsigned int tc_bytes_to_ticks(unsigned int rate, unsigned int size); static unsigned int tc_buffer_per_jiffy(unsigned int rate); +static struct tcmsg *netdev_linux_tc_make_request(const struct netdev *, + int type, + unsigned int flags, + struct ofpbuf *); -static struct tcmsg *tc_make_request(const struct netdev *, int type, - unsigned int flags, struct ofpbuf *); -static int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp); -static int tc_add_del_ingress_qdisc(struct netdev *netdev, bool add); static int tc_add_policer(struct netdev *, uint32_t kbits_rate, uint32_t kbits_burst); @@ -2055,12 +2050,18 @@ netdev_linux_set_policing(struct netdev *netdev_, struct netdev_linux *netdev = netdev_linux_cast(netdev_); const char *netdev_name = netdev_get_name(netdev_); int error; + int ifindex; kbits_burst = (!kbits_rate ? 0 /* Force to 0 if no rate specified. */ : !kbits_burst ? 8000 /* Default to 8000 kbits if 0. */ : kbits_burst); /* Stick with user-specified value. */ ovs_mutex_lock(&netdev->mutex); + error = get_ifindex(netdev_, &ifindex); + if (error) { + goto out; + } + if (netdev->cache_valid & VALID_POLICING) { error = netdev->netdev_policing_error; if (error || (netdev->kbits_rate == kbits_rate && @@ -2073,7 +2074,7 @@ netdev_linux_set_policing(struct netdev *netdev_, COVERAGE_INC(netdev_set_policing); /* Remove any existing ingress qdisc. */ - error = tc_add_del_ingress_qdisc(netdev_, false); + error = tc_add_del_ingress_qdisc(ifindex, false); if (error) { VLOG_WARN_RL(&rl, "%s: removing policing failed: %s", netdev_name, ovs_strerror(error)); @@ -2081,7 +2082,7 @@ netdev_linux_set_policing(struct netdev *netdev_, } if (kbits_rate) { - error = tc_add_del_ingress_qdisc(netdev_, true); + error = tc_add_del_ingress_qdisc(ifindex, true); if (error) { VLOG_WARN_RL(&rl, "%s: adding policing qdisc failed: %s", netdev_name, ovs_strerror(error)); @@ -2350,7 +2351,7 @@ start_queue_dump(const struct netdev *netdev, struct queue_dump_state *state) struct ofpbuf request; struct tcmsg *tcmsg; - tcmsg = tc_make_request(netdev, RTM_GETTCLASS, 0, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_GETTCLASS, 0, &request); if (!tcmsg) { return false; } @@ -2909,8 +2910,8 @@ codel_setup_qdisc__(struct netdev *netdev, uint32_t target, uint32_t limit, tc_del_qdisc(netdev); - tcmsg = tc_make_request(netdev, RTM_NEWQDISC, - NLM_F_EXCL | NLM_F_CREATE, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC, + NLM_F_EXCL | NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } @@ -3127,8 +3128,8 @@ fqcodel_setup_qdisc__(struct netdev *netdev, uint32_t target, uint32_t limit, tc_del_qdisc(netdev); - tcmsg = tc_make_request(netdev, RTM_NEWQDISC, - NLM_F_EXCL | NLM_F_CREATE, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC, + NLM_F_EXCL | NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } @@ -3351,8 +3352,8 @@ sfq_setup_qdisc__(struct netdev *netdev, uint32_t quantum, uint32_t perturb) tc_del_qdisc(netdev); - tcmsg = tc_make_request(netdev, RTM_NEWQDISC, - NLM_F_EXCL | NLM_F_CREATE, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC, + NLM_F_EXCL | NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } @@ -3538,8 +3539,8 @@ htb_setup_qdisc__(struct netdev *netdev) tc_del_qdisc(netdev); - tcmsg = tc_make_request(netdev, RTM_NEWQDISC, - NLM_F_EXCL | NLM_F_CREATE, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC, + NLM_F_EXCL | NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } @@ -3592,7 +3593,8 @@ htb_setup_class__(struct netdev *netdev, unsigned int handle, opt.cbuffer = tc_calc_buffer(opt.ceil.rate, mtu, class->burst); opt.prio = class->priority; - tcmsg = tc_make_request(netdev, RTM_NEWTCLASS, NLM_F_CREATE, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWTCLASS, + NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } @@ -4201,13 +4203,11 @@ hfsc_setup_qdisc__(struct netdev * netdev) tc_del_qdisc(netdev); - tcmsg = tc_make_request(netdev, RTM_NEWQDISC, - NLM_F_EXCL | NLM_F_CREATE, &request); - + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWQDISC, + NLM_F_EXCL | NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } - tcmsg->tcm_handle = tc_make_handle(1, 0); tcmsg->tcm_parent = TC_H_ROOT; @@ -4234,12 +4234,11 @@ hfsc_setup_class__(struct netdev *netdev, unsigned int handle, struct ofpbuf request; struct tc_service_curve min, max; - tcmsg = tc_make_request(netdev, RTM_NEWTCLASS, NLM_F_CREATE, &request); - + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWTCLASS, + NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } - tcmsg->tcm_handle = handle; tcmsg->tcm_parent = parent; @@ -4610,102 +4609,17 @@ static double ticks_per_s; */ static unsigned int buffer_hz; -/* Returns tc handle 'major':'minor'. */ -static unsigned int -tc_make_handle(unsigned int major, unsigned int minor) -{ - return TC_H_MAKE(major << 16, minor); -} - -/* Returns the major number from 'handle'. */ -static unsigned int -tc_get_major(unsigned int handle) -{ - return TC_H_MAJ(handle) >> 16; -} - -/* Returns the minor number from 'handle'. */ -static unsigned int -tc_get_minor(unsigned int handle) -{ - return TC_H_MIN(handle); -} - static struct tcmsg * -tc_make_request(const struct netdev *netdev, int type, unsigned int flags, - struct ofpbuf *request) +netdev_linux_tc_make_request(const struct netdev *netdev, int type, + unsigned int flags, struct ofpbuf *request) { - struct tcmsg *tcmsg; int ifindex; - int error; - error = get_ifindex(netdev, &ifindex); - if (error) { + if (get_ifindex(netdev, &ifindex)) { return NULL; } - ofpbuf_init(request, 512); - nl_msg_put_nlmsghdr(request, sizeof *tcmsg, type, NLM_F_REQUEST | flags); - tcmsg = ofpbuf_put_zeros(request, sizeof *tcmsg); - tcmsg->tcm_family = AF_UNSPEC; - tcmsg->tcm_ifindex = ifindex; - /* Caller should fill in tcmsg->tcm_handle. */ - /* Caller should fill in tcmsg->tcm_parent. */ - - return tcmsg; -} - -static int -tc_transact(struct ofpbuf *request, struct ofpbuf **replyp) -{ - int error = nl_transact(NETLINK_ROUTE, request, replyp); - ofpbuf_uninit(request); - return error; -} - -/* Adds or deletes a root ingress qdisc on 'netdev'. We use this for - * policing configuration. - * - * This function is equivalent to running the following when 'add' is true: - * /sbin/tc qdisc add dev <devname> handle ffff: ingress - * - * This function is equivalent to running the following when 'add' is false: - * /sbin/tc qdisc del dev <devname> handle ffff: ingress - * - * The configuration and stats may be seen with the following command: - * /sbin/tc -s qdisc show dev <devname> - * - * Returns 0 if successful, otherwise a positive errno value. - */ -static int -tc_add_del_ingress_qdisc(struct netdev *netdev, bool add) -{ - struct ofpbuf request; - struct tcmsg *tcmsg; - int error; - int type = add ? RTM_NEWQDISC : RTM_DELQDISC; - int flags = add ? NLM_F_EXCL | NLM_F_CREATE : 0; - - tcmsg = tc_make_request(netdev, type, flags, &request); - if (!tcmsg) { - return ENODEV; - } - tcmsg->tcm_handle = tc_make_handle(0xffff, 0); - tcmsg->tcm_parent = TC_H_INGRESS; - nl_msg_put_string(&request, TCA_KIND, "ingress"); - nl_msg_put_unspec(&request, TCA_OPTIONS, NULL, 0); - - error = tc_transact(&request, NULL); - if (error) { - /* If we're deleting the qdisc, don't worry about some of the - * error conditions. */ - if (!add && (error == ENOENT || error == EINVAL)) { - return 0; - } - return error; - } - - return 0; + return tc_make_request(ifindex, type, flags, request); } /* Adds a policer to 'netdev' with a rate of 'kbits_rate' and a burst size @@ -4748,8 +4662,8 @@ tc_add_policer(struct netdev *netdev, tc_police.burst = tc_bytes_to_ticks( tc_police.rate.rate, MIN(UINT32_MAX / 1024, kbits_burst) * 1024 / 8); - tcmsg = tc_make_request(netdev, RTM_NEWTFILTER, - NLM_F_EXCL | NLM_F_CREATE, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_NEWTFILTER, + NLM_F_EXCL | NLM_F_CREATE, &request); if (!tcmsg) { return ENODEV; } @@ -5014,7 +4928,8 @@ tc_query_class(const struct netdev *netdev, struct tcmsg *tcmsg; int error; - tcmsg = tc_make_request(netdev, RTM_GETTCLASS, NLM_F_ECHO, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_GETTCLASS, + NLM_F_ECHO, &request); if (!tcmsg) { return ENODEV; } @@ -5040,7 +4955,7 @@ tc_delete_class(const struct netdev *netdev, unsigned int handle) struct tcmsg *tcmsg; int error; - tcmsg = tc_make_request(netdev, RTM_DELTCLASS, 0, &request); + tcmsg = netdev_linux_tc_make_request(netdev, RTM_DELTCLASS, 0, &request); if (!tcmsg) { return ENODEV; } @@ -5066,7 +4981,7 @@ tc_del_qdisc(struct netdev *netdev_) struct tcmsg *tcmsg; int error; - tcmsg = tc_make_request(netdev_, RTM_DELQDISC, 0, &request); + tcmsg = netdev_linux_tc_make_request(netdev_, RTM_DELQDISC, 0, &request); if (!tcmsg) { return ENODEV; } @@ -5147,7 +5062,8 @@ tc_query_qdisc(const struct netdev *netdev_) * in such a case we get no response at all from the kernel (!) if a * builtin qdisc is in use (which is later caught by "!error && * !qdisc->size"). */ - tcmsg = tc_make_request(netdev_, RTM_GETQDISC, NLM_F_ECHO, &request); + tcmsg = netdev_linux_tc_make_request(netdev_, RTM_GETQDISC, + NLM_F_ECHO, &request); if (!tcmsg) { return ENODEV; } diff --git a/lib/tc.c b/lib/tc.c index acda7fe..431242b 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -39,44 +39,95 @@ VLOG_DEFINE_THIS_MODULE(tc); static struct vlog_rate_limit parse_err = VLOG_RATE_LIMIT_INIT(5, 5); /* Returns tc handle 'major':'minor'. */ -static unsigned int +unsigned int tc_make_handle(unsigned int major, unsigned int minor) { return TC_H_MAKE(major << 16, minor); } -static struct tcmsg * -tc_make_req(int ifindex, int type, unsigned int flags, struct ofpbuf *request) +/* Returns the major number from 'handle'. */ +unsigned int +tc_get_major(unsigned int handle) { - struct tcmsg *tcmsg; - struct nlmsghdr *nlmsghdr; + return TC_H_MAJ(handle) >> 16; +} - ofpbuf_init(request, 512); +/* Returns the minor number from 'handle'. */ +unsigned int +tc_get_minor(unsigned int handle) +{ + return TC_H_MIN(handle); +} - nl_msg_reserve(request, NLMSG_HDRLEN + sizeof *tcmsg); - nlmsghdr = nl_msg_put_uninit(request, NLMSG_HDRLEN); - nlmsghdr->nlmsg_len = 0; - nlmsghdr->nlmsg_type = type; - nlmsghdr->nlmsg_flags = NLM_F_REQUEST | flags; - nlmsghdr->nlmsg_seq = 0; - nlmsghdr->nlmsg_pid = 0; +struct tcmsg * +tc_make_request(int ifindex, int type, unsigned int flags, + struct ofpbuf *request) +{ + struct tcmsg *tcmsg; + ofpbuf_init(request, 512); + nl_msg_put_nlmsghdr(request, sizeof *tcmsg, type, NLM_F_REQUEST | flags); tcmsg = ofpbuf_put_zeros(request, sizeof *tcmsg); tcmsg->tcm_family = AF_UNSPEC; tcmsg->tcm_ifindex = ifindex; + /* Caller should fill in tcmsg->tcm_handle. */ + /* Caller should fill in tcmsg->tcm_parent. */ return tcmsg; } -static int +int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp) { int error = nl_transact(NETLINK_ROUTE, request, replyp); - ofpbuf_uninit(request); return error; } +/* Adds or deletes a root ingress qdisc on device with specified ifindex. + * + * This function is equivalent to running the following when 'add' is true: + * /sbin/tc qdisc add dev <devname> handle ffff: ingress + * + * This function is equivalent to running the following when 'add' is false: + * /sbin/tc qdisc del dev <devname> handle ffff: ingress + * + * Where dev <devname> is the device with specified ifindex name. + * + * The configuration and stats may be seen with the following command: + * /sbin/tc -s qdisc show dev <devname> + * + * + * Returns 0 if successful, otherwise a positive errno value. + */ +int +tc_add_del_ingress_qdisc(int ifindex, bool add) +{ + struct ofpbuf request; + struct tcmsg *tcmsg; + int error; + int type = add ? RTM_NEWQDISC : RTM_DELQDISC; + int flags = add ? NLM_F_EXCL | NLM_F_CREATE : 0; + + tcmsg = tc_make_request(ifindex, type, flags, &request); + tcmsg->tcm_handle = tc_make_handle(0xffff, 0); + tcmsg->tcm_parent = TC_H_INGRESS; + nl_msg_put_string(&request, TCA_KIND, "ingress"); + nl_msg_put_unspec(&request, TCA_OPTIONS, NULL, 0); + + error = tc_transact(&request, NULL); + if (error) { + /* If we're deleting the qdisc, don't worry about some of the + * error conditions. */ + if (!add && (error == ENOENT || error == EINVAL)) { + return 0; + } + return error; + } + + return 0; +} + static const struct nl_policy tca_policy[] = { [TCA_KIND] = { .type = NL_A_STRING, .optional = false, }, [TCA_OPTIONS] = { .type = NL_A_NESTED, .optional = false, }, diff --git a/lib/tc.h b/lib/tc.h index d377101..5ca6c55 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -17,9 +17,20 @@ #ifndef TC_H #define TC_H 1 +#include <linux/pkt_cls.h> +#include <linux/pkt_sched.h> #include "odp-netlink.h" #include "netlink-socket.h" +#define TC_POLICY_DEFAULT "none" + +unsigned int tc_make_handle(unsigned int major, unsigned int minor); +unsigned int tc_get_major(unsigned int handle); +unsigned int tc_get_minor(unsigned int handle); +struct tcmsg *tc_make_request(int ifindex, int type, unsigned int flags, + struct ofpbuf *request); +int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp); +int tc_add_del_ingress_qdisc(int ifindex, bool add); struct tc_flower_key { ovs_be16 eth_type; -- 2.7.4 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev