From d28c1de1f918967a31cf1fa1cf34916295142962 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czarnota Date: Fri, 11 Sep 2020 14:38:28 +0200 Subject: colmark: add colmark action --- Makefile.am | 3 + .../linux-private/linux/tc_act/tc_colmark.h | 45 +++ include/netlink-private/types.h | 11 + include/netlink/route/act/colmark.h | 51 +++ lib/route/act/colmark.c | 334 ++++++++++++++++++ libnl-route-3.sym | 6 + 6 files changed, 450 insertions(+) create mode 100644 include/linux-private/linux/tc_act/tc_colmark.h create mode 100644 include/netlink/route/act/colmark.h create mode 100644 lib/route/act/colmark.c --- a/Makefile.am +++ b/Makefile.am @@ -123,6 +123,7 @@ libnlinclude_netlink_route_act_HEADERS = include/netlink/route/act/mirred.h \ include/netlink/route/act/skbedit.h \ include/netlink/route/act/vlan.h \ + include/netlink/route/act/colmark.h \ $(NULL) libnlinclude_netlink_route_clsdir = $(libnlincludedir)/netlink/route/cls libnlinclude_netlink_route_cls_HEADERS = \ @@ -257,6 +258,7 @@ noinst_HEADERS = \ include/linux-private/linux/socket.h \ include/linux-private/linux/tc_act/tc_gact.h \ include/linux-private/linux/tc_act/tc_mirred.h \ + include/linux-private/linux/tc_act/tc_colmark.h \ include/linux-private/linux/tc_act/tc_skbedit.h \ include/linux-private/linux/tc_act/tc_vlan.h \ include/linux-private/linux/tc_ematch/tc_em_meta.h \ @@ -383,6 +385,7 @@ lib_libnl_route_3_la_SOURCES = \ lib/route/cls.c \ lib/route/cls/basic.c \ lib/route/cls/cgroup.c \ + lib/route/act/colmark.c \ lib/route/cls/ematch.c \ lib/route/cls/ematch/cmp.c \ lib/route/cls/ematch/container.c \ --- /dev/null +++ b/include/linux-private/linux/tc_act/tc_colmark.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_COLMARK_H +#define __LINUX_TC_COLMARK_H + +#include + +#define TCA_ACT_COLMARK 27 + +#define COLMARK_F_MODE 0x1 +#define COLMARK_F_DROP_PRECEDENCE 0x2 +#define COLMARK_F_METER_TYPE 0x4 + +enum tc_drop_precedence { + TC_COLMARK_NO_MARKING, + TC_COLMARK_INTERNAL = 1, + TC_COLMARK_DEI = 2, + TC_COLMARK_PCP_8P0D = 3, + TC_COLMARK_PCP_7P1D = 4, + TC_COLMARK_PCP_6P2D = 5, + TC_COLMARK_PCP_5P3D = 6, + TC_COLMARK_DSCP_AF = 7, +}; + +enum tc_meter_type { + TC_COLMARK_SRTCM, + TC_COLMARK_TRTCM, +}; + +struct tc_colmark { + tc_gen; +}; + +enum { + TCA_COLMARK_UNSPEC, + TCA_COLMARK_TM, + TCA_COLMARK_PARMS, + TCA_COLMARK_MODE, + TCA_COLMARK_DROP_PRECEDENCE, + TCA_COLMARK_METER_TYPE, + TCA_COLMARK_PAD, + __TCA_COLMARK_MAX +}; +#define TCA_COLMARK_MAX (__TCA_COLMARK_MAX - 1) + +#endif --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -574,6 +576,15 @@ struct rtnl_act struct rtnl_act * a_next; }; +struct rtnl_colmark +{ + struct tc_colmark c_parm; + uint8_t c_mode; + uint8_t c_drop_precedence; + uint8_t c_meter_type; + uint32_t c_flags; +}; + struct rtnl_mirred { struct tc_mirred m_parm; --- /dev/null +++ b/include/netlink/route/act/colmark.h @@ -0,0 +1,51 @@ +/* + * netlink/route/act/colmark.h colmark action + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2019 Intel Corporation + */ + +#ifndef NETLINK_COLMARK_H_ +#define NETLINK_COLMARK_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum colmark_drop_precedence { + COLMARK_NO_MARKING, + COLMARK_INTERNAL, + COLMARK_DEI, + COLMARK_PCP_8P0D, + COLMARK_PCP_7P1D, + COLMARK_PCP_6P2D, + COLMARK_PCP_5P3D, + COLMARK_DSCP_AF, +}; + +enum colmark_meter_type { + /* Single Rate Three Color Marker RFC2697 */ + COLMARK_SRTCM, + /* Two Rate Three Color Marker RFC2698 */ + COLMARK_TRTCM, +}; + +extern int rtnl_colmark_set_mode(struct rtnl_act *, uint32_t); +extern int rtnl_colmark_get_mode(struct rtnl_act *, uint32_t *); +extern int rtnl_colmark_set_drop_precedence(struct rtnl_act *, uint32_t); +extern int rtnl_colmark_get_drop_precedence(struct rtnl_act *, uint32_t *); +extern int rtnl_colmark_set_meter_type(struct rtnl_act *, uint32_t); +extern int rtnl_colmark_get_meter_type(struct rtnl_act *, uint32_t *); + +#ifdef __cplusplus +} +#endif +#endif --- /dev/null +++ b/lib/route/act/colmark.c @@ -0,0 +1,334 @@ +/* + * lib/route/act/colmark.c colmark action + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2019 Intel Corporation + */ + +/** + * @ingroup act + * @defgroup act_colmark Colmark Editing + * + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct nla_policy colmark_policy[TCA_COLMARK_MAX + 1] = { + [TCA_COLMARK_PARMS] = {.minlen = sizeof(struct tc_colmark)}, + [TCA_COLMARK_MODE] = {.type = NLA_U8}, + [TCA_COLMARK_DROP_PRECEDENCE] = {.type = NLA_U8}, + [TCA_COLMARK_METER_TYPE] = {.type = NLA_U8}, +}; + +static int colmark_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_colmark *u = data; + struct nlattr *tb[TCA_COLMARK_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_COLMARK_MAX, tc, colmark_policy); + if (err < 0) + return err; + + if (tb[TCA_COLMARK_PARMS]) + nla_memcpy(&u->c_parm, tb[TCA_COLMARK_PARMS], + sizeof(u->c_parm)); + else + return -NLE_MISSING_ATTR; + + u->c_flags = 0; + if (tb[TCA_COLMARK_MODE]) { + u->c_flags |= COLMARK_F_MODE; + u->c_mode = nla_get_u8(tb[TCA_COLMARK_MODE]); + } + + if (tb[TCA_COLMARK_DROP_PRECEDENCE]) { + u->c_flags |= COLMARK_F_DROP_PRECEDENCE; + u->c_drop_precedence = + nla_get_u8(tb[TCA_COLMARK_DROP_PRECEDENCE]); + } + + if (tb[TCA_COLMARK_METER_TYPE]) { + u->c_flags |= COLMARK_F_METER_TYPE; + u->c_meter_type = nla_get_u8(tb[TCA_COLMARK_METER_TYPE]); + } + + return 0; +} + +static int colmark_clone(void *_dst, void *_src) +{ + struct rtnl_colmark *dst = _dst, *src = _src; + + memcpy(&dst->c_parm, &src->c_parm, sizeof(src->c_parm)); + return 0; +} + +static void colmark_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_colmark *u = data; + + if (!u) + return; + + nl_dump(p, " mode %u, drop_prcedence %u, meter_type %u", + u->c_mode, u->c_drop_precedence, u->c_meter_type); +} + +static void colmark_dump_details(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_colmark *u = data; + + if (!u) + return; + + if (u->c_flags & COLMARK_F_MODE) + nl_dump(p, " mode %u", u->c_mode); + + if (u->c_flags & COLMARK_F_DROP_PRECEDENCE) + nl_dump(p, " drop_precedence %u", u->c_drop_precedence); + + if (u->c_flags & COLMARK_F_METER_TYPE) + nl_dump(p, " meter_type %u", u->c_meter_type); + + nl_dump(p, "\n"); +} + +static int colmark_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg) +{ + struct rtnl_colmark *u = data; + + if (!u) + return 0; + + NLA_PUT(msg, TCA_COLMARK_PARMS, sizeof(u->c_parm), &u->c_parm); + + if (u->c_flags & COLMARK_F_MODE) + NLA_PUT_U8(msg, TCA_COLMARK_MODE, u->c_mode); + + if (u->c_flags & COLMARK_F_DROP_PRECEDENCE) + NLA_PUT_U8(msg, TCA_COLMARK_DROP_PRECEDENCE, + u->c_drop_precedence); + + if (u->c_flags & COLMARK_F_METER_TYPE) + NLA_PUT_U8(msg, TCA_COLMARK_METER_TYPE, u->c_meter_type); + + return 0; + +nla_put_failure: + return -NLE_NOMEM; +} + +/** + * @name Attribute Modifications + * @{ + */ + +int rtnl_colmark_set_mode(struct rtnl_act *act, uint32_t mode) +{ + struct rtnl_colmark *u; + + u = (struct rtnl_colmark *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + + u->c_mode = mode; + u->c_flags |= COLMARK_F_MODE; + + return 0; +} + +int rtnl_colmark_get_mode(struct rtnl_act *act, uint32_t *mode) +{ + struct rtnl_colmark *u; + + u = (struct rtnl_colmark *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + + if (!(u->c_flags & COLMARK_F_MODE)) + return -NLE_NOATTR; + + *mode = u->c_mode; + + return 0; +} + +int rtnl_colmark_set_drop_precedence(struct rtnl_act *act, uint32_t dp) +{ + struct rtnl_colmark *u; + uint32_t tc_dp; + + u = (struct rtnl_colmark *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + + switch (dp) { + case COLMARK_NO_MARKING: + tc_dp = TC_COLMARK_NO_MARKING; + break; + case COLMARK_INTERNAL: + tc_dp = TC_COLMARK_INTERNAL; + break; + case COLMARK_DEI: + tc_dp = TC_COLMARK_DEI; + break; + case COLMARK_PCP_8P0D: + tc_dp = TC_COLMARK_PCP_8P0D; + break; + case COLMARK_PCP_7P1D: + tc_dp = TC_COLMARK_PCP_7P1D; + break; + case COLMARK_PCP_6P2D: + tc_dp = TC_COLMARK_PCP_6P2D; + break; + case COLMARK_PCP_5P3D: + tc_dp = TC_COLMARK_PCP_5P3D; + break; + case COLMARK_DSCP_AF: + tc_dp = TC_COLMARK_DSCP_AF; + break; + default: + return -NLE_INVAL; + } + + u->c_drop_precedence = tc_dp; + u->c_flags |= COLMARK_F_DROP_PRECEDENCE; + + return 0; +} + +int rtnl_colmark_get_drop_precedence(struct rtnl_act *act, uint32_t *dp) +{ + struct rtnl_colmark *u; + + u = (struct rtnl_colmark *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + + if (!(u->c_flags & COLMARK_F_DROP_PRECEDENCE)) + return -NLE_NOATTR; + + switch (u->c_drop_precedence) { + case TC_COLMARK_NO_MARKING: + *dp = COLMARK_NO_MARKING; + break; + case TC_COLMARK_INTERNAL: + *dp = COLMARK_INTERNAL; + break; + case TC_COLMARK_DEI: + *dp = COLMARK_DEI; + break; + case TC_COLMARK_PCP_8P0D: + *dp = COLMARK_PCP_8P0D; + break; + case TC_COLMARK_PCP_7P1D: + *dp = COLMARK_PCP_7P1D; + break; + case TC_COLMARK_PCP_6P2D: + *dp = COLMARK_PCP_6P2D; + break; + case TC_COLMARK_PCP_5P3D: + *dp = COLMARK_PCP_5P3D; + break; + case TC_COLMARK_DSCP_AF: + *dp = COLMARK_DSCP_AF; + break; + default: + return -NLE_INVAL; + } + + return 0; +} + +int rtnl_colmark_set_meter_type(struct rtnl_act *act, uint32_t mt) +{ + struct rtnl_colmark *u; + uint32_t tc_mt; + + u = (struct rtnl_colmark *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + + switch (mt) { + case COLMARK_SRTCM: + tc_mt = TC_COLMARK_SRTCM; + break; + case COLMARK_TRTCM: + tc_mt = TC_COLMARK_TRTCM; + break; + default: + return -NLE_INVAL; + } + + u->c_meter_type = tc_mt; + u->c_flags |= COLMARK_F_METER_TYPE; + + return 0; +} + +int rtnl_colmark_get_meter_type(struct rtnl_act *act, uint32_t *mt) +{ + struct rtnl_colmark *u; + + u = (struct rtnl_colmark *) rtnl_tc_data(TC_CAST(act)); + if (!u) + return -NLE_NOMEM; + + if (!(u->c_flags & COLMARK_F_METER_TYPE)) + return -NLE_NOATTR; + + switch (u->c_meter_type) { + case TC_COLMARK_SRTCM: + *mt = COLMARK_SRTCM; + break; + case TC_COLMARK_TRTCM: + *mt = COLMARK_TRTCM; + break; + default: + return -NLE_INVAL; + } + + return 0; +} + +/** @} */ + +static struct rtnl_tc_ops colmark_ops = { + .to_kind = "colmark", + .to_type = RTNL_TC_TYPE_ACT, + .to_size = sizeof(struct rtnl_colmark), + .to_msg_parser = colmark_msg_parser, + .to_clone = colmark_clone, + .to_msg_fill = colmark_msg_fill, + .to_dump = { + [NL_DUMP_LINE] = colmark_dump_line, + [NL_DUMP_DETAILS] = colmark_dump_details, + }, +}; + +static void __init colmark_init(void) +{ + rtnl_tc_register(&colmark_ops); +} + +static void __exit colmark_exit(void) +{ + rtnl_tc_unregister(&colmark_ops); +} + +/** @} */ --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -161,6 +161,12 @@ global: rtnl_cls_put; rtnl_cls_set_prio; rtnl_cls_set_protocol; + rtnl_colmark_get_drop_precedence; + rtnl_colmark_get_meter_type; + rtnl_colmark_get_mode; + rtnl_colmark_set_drop_precedence; + rtnl_colmark_set_meter_type; + rtnl_colmark_set_mode; rtnl_ematch_add_child; rtnl_ematch_alloc; rtnl_ematch_cmp_get;