On 22 March 2017 at 04:10, Roi Dayan <[email protected]> wrote: > From: Paul Blakey <[email protected]> > > Add tc flower interface that will be used to offload flows via tc > flower classifier. Depending on the flag used (skip_sw/hw) flower > will pass those to HW or handle them itself. > Move some tc related functions from netdev-linux.c to tc.c > > Co-authored-by: Shahar Klein <[email protected]> > Signed-off-by: Shahar Klein <[email protected]> > Signed-off-by: Paul Blakey <[email protected]> > Reviewed-by: Roi Dayan <[email protected]> > --- > lib/automake.mk | 2 + > lib/netdev-linux.c | 164 ++------ > lib/tc.c | 1108 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/tc.h | 127 ++++++ > 4 files changed, 1277 insertions(+), 124 deletions(-) > create mode 100644 lib/tc.c > create mode 100644 lib/tc.h > > diff --git a/lib/automake.mk b/lib/automake.mk > index abc9d0d..a6141ea 100644 > --- a/lib/automake.mk > +++ b/lib/automake.mk > @@ -351,6 +351,8 @@ if LINUX > lib_libopenvswitch_la_SOURCES += \ > lib/dpif-netlink.c \ > lib/dpif-netlink.h \ > + lib/tc.h \ > + lib/tc.c \ > lib/if-notifier.c \ > lib/if-notifier.h \ > lib/netdev-linux.c \ > 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 > new file mode 100644 > index 0000000..b1ffe75 > --- /dev/null > +++ b/lib/tc.c > @@ -0,0 +1,1108 @@ > +/* > + * Copyright (c) 2016 Mellanox Technologies, Ltd.
Several of the common tc library functions were refactored out of netdev-linux, which I would have expected to retain the Nicira copyright. Please add the Nicira copyright here as well. If you wish to make this more clear, I would suggest splitting this patch into the pieces that are refactored from existing code, then adding the flower changes in a separate patch. _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
