diff options
| author | Siger Yang <siger.yang@outlook.com> | 2022-09-06 15:13:23 +0800 | 
|---|---|---|
| committer | Siger Yang <siger.yang@outlook.com> | 2022-11-22 22:35:35 +0800 | 
| commit | dfacea4ae7001346ea5e21fce485db5255e809f6 (patch) | |
| tree | 161f876506910bd56ea76be2e843f6766d97a31b /zebra/zapi_msg.c | |
| parent | c317d3f246769e8261df0f9d1eb787bea7b5da06 (diff) | |
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>
Diffstat (limited to 'zebra/zapi_msg.c')
| -rw-r--r-- | zebra/zapi_msg.c | 172 | 
1 files changed, 172 insertions, 0 deletions
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 130fb972db..d594512b36 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,  };  /*  | 
