diff options
author | Siger Yang <siger.yang@outlook.com> | 2022-09-06 09:13:23 +0200 |
---|---|---|
committer | Siger Yang <siger.yang@outlook.com> | 2022-11-22 15:35:35 +0100 |
commit | dfacea4ae7001346ea5e21fce485db5255e809f6 (patch) | |
tree | 161f876506910bd56ea76be2e843f6766d97a31b | |
parent | zebra: traffic control state management (diff) | |
download | frr-dfacea4ae7001346ea5e21fce485db5255e809f6.tar.xz frr-dfacea4ae7001346ea5e21fce485db5255e809f6.zip |
zebra: traffic control ZAPI
This commit adds ZAPI encoders & decoders for traffic control operations, which
include tc_qdisc, tc_class and tc_filter.
Signed-off-by: Siger Yang <siger.yang@outlook.com>
-rw-r--r-- | lib/zclient.c | 91 | ||||
-rw-r--r-- | lib/zclient.h | 6 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 172 |
3 files changed, 269 insertions, 0 deletions
diff --git a/lib/zclient.c b/lib/zclient.c index fd6eb7db0..07c7e5aea 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -37,6 +37,7 @@ #include "mpls.h" #include "sockopt.h" #include "pbr.h" +#include "tc.h" #include "nexthop_group.h" #include "lib_errors.h" #include "srte.h" @@ -1649,6 +1650,96 @@ int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, struct pbr_rule *zrule) return 0; } +int zapi_tc_qdisc_encode(uint8_t cmd, struct stream *s, struct tc_qdisc *qdisc) +{ + stream_reset(s); + zclient_create_header(s, cmd, VRF_DEFAULT); + + + stream_putl(s, 1); + + stream_putl(s, qdisc->ifindex); + stream_putl(s, qdisc->kind); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return 0; +} + +int zapi_tc_class_encode(uint8_t cmd, struct stream *s, struct tc_class *class) +{ + stream_reset(s); + zclient_create_header(s, cmd, VRF_DEFAULT); + + stream_putl(s, 1); + + stream_putl(s, class->ifindex); + stream_putl(s, class->handle); + stream_putl(s, class->kind); + + switch (class->kind) { + case TC_QDISC_HTB: + stream_putq(s, class->u.htb.rate); + stream_putq(s, class->u.htb.ceil); + break; + default: + /* not implemented */ + break; + } + stream_putw_at(s, 0, stream_get_endp(s)); + + return 0; +} + +int zapi_tc_filter_encode(uint8_t cmd, struct stream *s, + struct tc_filter *filter) +{ + stream_reset(s); + zclient_create_header(s, cmd, VRF_DEFAULT); + + stream_putl(s, 1); + + stream_putl(s, filter->ifindex); + stream_putl(s, filter->handle); + stream_putl(s, filter->priority); + stream_putl(s, filter->protocol); + stream_putl(s, filter->kind); + + switch (filter->kind) { + case TC_FILTER_FLOWER: + stream_putl(s, filter->u.flower.filter_bm); + if (filter->u.flower.filter_bm & TC_FLOWER_IP_PROTOCOL) + stream_putc(s, filter->u.flower.ip_proto); + if (filter->u.flower.filter_bm & TC_FLOWER_SRC_IP) + zapi_encode_prefix(s, &filter->u.flower.src_ip, + filter->u.flower.src_ip.family); + if (filter->u.flower.filter_bm & TC_FLOWER_SRC_PORT) { + stream_putw(s, filter->u.flower.src_port_min); + stream_putw(s, filter->u.flower.src_port_max); + } + if (filter->u.flower.filter_bm & TC_FLOWER_DST_IP) + zapi_encode_prefix(s, &filter->u.flower.dst_ip, + filter->u.flower.dst_ip.family); + if (filter->u.flower.filter_bm & TC_FLOWER_DST_PORT) { + stream_putw(s, filter->u.flower.dst_port_min); + stream_putw(s, filter->u.flower.dst_port_max); + } + if (filter->u.flower.filter_bm & TC_FLOWER_DSFIELD) { + stream_putc(s, filter->u.flower.dsfield); + stream_putc(s, filter->u.flower.dsfield_mask); + } + stream_putl(s, filter->u.flower.classid); + break; + default: + /* not implemented */ + break; + } + + stream_putw_at(s, 0, stream_get_endp(s)); + + return 0; +} + bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id, enum zapi_nhg_notify_owner *note) { diff --git a/lib/zclient.h b/lib/zclient.h index 731769abf..584a42194 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -243,6 +243,12 @@ typedef enum { ZEBRA_GRE_GET, ZEBRA_GRE_UPDATE, ZEBRA_GRE_SOURCE_SET, + ZEBRA_TC_QDISC_INSTALL, + ZEBRA_TC_QDISC_UNINSTALL, + ZEBRA_TC_CLASS_ADD, + ZEBRA_TC_CLASS_DELETE, + ZEBRA_TC_FILTER_ADD, + ZEBRA_TC_FILTER_DELETE, } zebra_message_types_t; enum zebra_error_types { diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 130fb972d..d594512b3 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -53,6 +53,7 @@ #include "zebra/zebra_evpn_mh.h" #include "zebra/rt.h" #include "zebra/zebra_pbr.h" +#include "zebra/zebra_tc.h" #include "zebra/table_manager.h" #include "zebra/zapi_msg.h" #include "zebra/zebra_errors.h" @@ -3272,6 +3273,171 @@ stream_failure: return; } +static inline void zread_tc_qdisc(ZAPI_HANDLER_ARGS) +{ + struct zebra_tc_qdisc qdisc; + struct stream *s; + uint32_t total, i; + + s = msg; + STREAM_GETL(s, total); + + for (i = 0; i < total; i++) { + memset(&qdisc, 0, sizeof(qdisc)); + + qdisc.sock = client->sock; + STREAM_GETL(s, qdisc.qdisc.ifindex); + STREAM_GETL(s, qdisc.qdisc.kind); + + if (hdr->command == ZEBRA_TC_QDISC_INSTALL) + zebra_tc_qdisc_install(&qdisc); + else + zebra_tc_qdisc_uninstall(&qdisc); + } + +stream_failure: + return; +} + +static inline void zread_tc_class(ZAPI_HANDLER_ARGS) +{ + struct zebra_tc_class class; + struct stream *s; + uint32_t total, i; + + s = msg; + STREAM_GETL(s, total); + + for (i = 0; i < total; i++) { + memset(&class, 0, sizeof(class)); + + class.sock = client->sock; + STREAM_GETL(s, class.class.ifindex); + STREAM_GETL(s, class.class.handle); + STREAM_GETL(s, class.class.kind); + STREAM_GETQ(s, class.class.u.htb.rate); + STREAM_GETQ(s, class.class.u.htb.ceil); + + if (hdr->command == ZEBRA_TC_CLASS_ADD) + zebra_tc_class_add(&class); + else + zebra_tc_class_delete(&class); + } + +stream_failure: + return; +} + +static inline void zread_tc_filter(ZAPI_HANDLER_ARGS) +{ + struct zebra_tc_filter filter; + struct stream *s; + uint32_t total, i; + + s = msg; + STREAM_GETL(s, total); + + for (i = 0; i < total; i++) { + memset(&filter, 0, sizeof(filter)); + + filter.sock = client->sock; + STREAM_GETL(s, filter.filter.ifindex); + STREAM_GETL(s, filter.filter.handle); + STREAM_GETL(s, filter.filter.priority); + STREAM_GETL(s, filter.filter.protocol); + STREAM_GETL(s, filter.filter.kind); + switch (filter.filter.kind) { + case TC_FILTER_FLOWER: { + STREAM_GETL(s, filter.filter.u.flower.filter_bm); + uint32_t filter_bm = filter.filter.u.flower.filter_bm; + + if (filter_bm & TC_FLOWER_IP_PROTOCOL) + STREAM_GETC(s, filter.filter.u.flower.ip_proto); + if (filter_bm & TC_FLOWER_SRC_IP) { + STREAM_GETC( + s, + filter.filter.u.flower.src_ip.family); + STREAM_GETC(s, filter.filter.u.flower.src_ip + .prefixlen); + STREAM_GET( + &filter.filter.u.flower.src_ip.u.prefix, + s, + prefix_blen(&filter.filter.u.flower + .src_ip)); + + if (!(filter.filter.u.flower.src_ip.family == + AF_INET || + filter.filter.u.flower.src_ip.family == + AF_INET6)) { + zlog_warn( + "Unsupported TC source IP family: %s (%hhu)", + family2str( + filter.filter.u.flower + .src_ip.family), + filter.filter.u.flower.src_ip + .family); + return; + } + } + if (filter_bm & TC_FLOWER_SRC_PORT) { + STREAM_GETW( + s, filter.filter.u.flower.src_port_min); + STREAM_GETW( + s, filter.filter.u.flower.src_port_max); + } + if (filter_bm & TC_FLOWER_DST_IP) { + STREAM_GETC( + s, + filter.filter.u.flower.dst_ip.family); + STREAM_GETC(s, filter.filter.u.flower.dst_ip + .prefixlen); + STREAM_GET( + &filter.filter.u.flower.dst_ip.u.prefix, + s, + prefix_blen(&filter.filter.u.flower + .dst_ip)); + if (!(filter.filter.u.flower.dst_ip.family == + AF_INET || + filter.filter.u.flower.dst_ip.family == + AF_INET6)) { + zlog_warn( + "Unsupported TC destination IP family: %s (%hhu)", + family2str( + filter.filter.u.flower + .dst_ip.family), + filter.filter.u.flower.dst_ip + .family); + return; + } + } + if (filter_bm & TC_FLOWER_DST_PORT) { + STREAM_GETW( + s, filter.filter.u.flower.dst_port_min); + STREAM_GETW( + s, filter.filter.u.flower.dst_port_max); + } + if (filter_bm & TC_FLOWER_DSFIELD) { + STREAM_GETC(s, filter.filter.u.flower.dsfield); + STREAM_GETC( + s, filter.filter.u.flower.dsfield_mask); + } + STREAM_GETL(s, filter.filter.u.flower.classid); + break; + } + default: + break; + } + + if (hdr->command == ZEBRA_TC_FILTER_ADD) + zebra_tc_filter_add(&filter); + else + zebra_tc_filter_delete(&filter); + } + +stream_failure: + return; +} + static inline void zread_ipset(ZAPI_HANDLER_ARGS) { struct zebra_pbr_ipset zpi; @@ -3772,6 +3938,12 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp, [ZEBRA_GRE_GET] = zebra_gre_get, [ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set, + [ZEBRA_TC_QDISC_INSTALL] = zread_tc_qdisc, + [ZEBRA_TC_QDISC_UNINSTALL] = zread_tc_qdisc, + [ZEBRA_TC_CLASS_ADD] = zread_tc_class, + [ZEBRA_TC_CLASS_DELETE] = zread_tc_class, + [ZEBRA_TC_FILTER_ADD] = zread_tc_filter, + [ZEBRA_TC_FILTER_DELETE] = zread_tc_filter, }; /* |