mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 07:36:46 +00:00
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>
This commit is contained in:
parent
c317d3f246
commit
dfacea4ae7
@ -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)
|
||||
{
|
||||
|
@ -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 {
|
||||
|
172
zebra/zapi_msg.c
172
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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user