diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/lib_vty.c | 12 | ||||
| -rw-r--r-- | lib/smux.h | 10 | ||||
| -rw-r--r-- | lib/subdir.am | 2 | ||||
| -rw-r--r-- | lib/tc.c | 88 | ||||
| -rw-r--r-- | lib/tc.h | 151 | ||||
| -rw-r--r-- | lib/vrf.c | 1 | ||||
| -rw-r--r-- | lib/zclient.c | 91 | ||||
| -rw-r--r-- | lib/zclient.h | 6 |
8 files changed, 351 insertions, 10 deletions
diff --git a/lib/lib_vty.c b/lib/lib_vty.c index 85816c5123..46a0a68103 100644 --- a/lib/lib_vty.c +++ b/lib/lib_vty.c @@ -225,10 +225,8 @@ static struct call_back { } callback; -DEFUN_HIDDEN (start_config, - start_config_cmd, - "XFRR_start_configuration", - "The Beginning of Configuration\n") +DEFUN_NOSH(start_config, start_config_cmd, "XFRR_start_configuration", + "The Beginning of Configuration\n") { callback.readin_time = monotime(NULL); @@ -240,10 +238,8 @@ DEFUN_HIDDEN (start_config, return CMD_SUCCESS; } -DEFUN_HIDDEN (end_config, - end_config_cmd, - "XFRR_end_configuration", - "The End of Configuration\n") +DEFUN_NOSH(end_config, end_config_cmd, "XFRR_end_configuration", + "The End of Configuration\n") { time_t readin_time; char readin_time_str[MONOTIME_STRLEN]; diff --git a/lib/smux.h b/lib/smux.h index 74447341d8..48c3374236 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -44,6 +44,7 @@ extern "C" { #define SNMP_INVALID 2 #define IN_ADDR_SIZE sizeof(struct in_addr) +#define IN6_ADDR_SIZE sizeof(struct in6_addr) /* IANAipRouteProtocol */ #define IANAIPROUTEPROTOCOLOTHER 1 @@ -87,8 +88,9 @@ struct index_oid { /* Declare SMUX return value. */ #define SNMP_LOCAL_VARIABLES \ static long snmp_int_val __attribute__((unused)); \ - static struct in_addr snmp_in_addr_val __attribute__((unused)); - static uint8_t snmp_octet_val __attribute__((unused)); + static struct in_addr snmp_in_addr_val __attribute__((unused)); \ + static uint8_t snmp_octet_val __attribute__((unused)); \ + static char snmp_string_val[255] __attribute__((unused)); #define SNMP_INTEGER(V) \ (*var_len = sizeof(snmp_int_val), snmp_int_val = V, \ (uint8_t *)&snmp_int_val) @@ -97,6 +99,10 @@ struct index_oid { (*var_len = sizeof(snmp_octet_val), snmp_octet_val = V, \ (uint8_t *)&snmp_octet_val) +#define SNMP_STRING(V) \ + (*var_len = MIN(sizeof(snmp_string_val), strlen(V) + 1), \ + strlcpy(snmp_string_val, V, *var_len), (uint8_t *)&snmp_string_val) + #define SNMP_IPADDRESS(V) \ (*var_len = sizeof(struct in_addr), snmp_in_addr_val = V, \ (uint8_t *)&snmp_in_addr_val) diff --git a/lib/subdir.am b/lib/subdir.am index ea6cb9339a..1a8c184823 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -123,6 +123,7 @@ lib_libfrr_la_SOURCES = \ lib/printf/glue.c \ lib/routing_nb.c \ lib/routing_nb_config.c \ + lib/tc.c \ # end nodist_lib_libfrr_la_SOURCES = \ @@ -275,6 +276,7 @@ pkginclude_HEADERS += \ lib/zlog_live.h \ lib/zlog_targets.h \ lib/pbr.h \ + lib/tc.h \ lib/routing_nb.h \ \ lib/assert/assert.h \ diff --git a/lib/tc.c b/lib/tc.c new file mode 100644 index 0000000000..1bc01ed3f6 --- /dev/null +++ b/lib/tc.c @@ -0,0 +1,88 @@ +/* + * Traffic Control (TC) main library + * Copyright (C) 2022 Shichu Yang + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tc.h" + +int tc_getrate(const char *str, uint64_t *rate) +{ + char *endp; + uint64_t raw = strtoull(str, &endp, 10); + + if (endp == str) + return -1; + + /* if the string only contains a number, it must be valid rate (bps) */ + bool valid = (*endp == '\0'); + + const char *p = endp; + bool bytes = false, binary_base = false; + int power = 0; + + while (*p) { + if (strcmp(p, "Bps") == 0) { + bytes = true; + valid = true; + break; + } else if (strcmp(p, "bit") == 0) { + valid = true; + break; + } + switch (*p) { + case 'k': + case 'K': + power = 1; + break; + case 'm': + case 'M': + power = 2; + break; + case 'g': + case 'G': + power = 3; + break; + case 't': + case 'T': + power = 4; + break; + case 'i': + case 'I': + if (power != 0) + binary_base = true; + else + return -1; + break; + default: + return -1; + } + p++; + } + + if (!valid) + return -1; + + for (int i = 0; i < power; i++) + raw *= binary_base ? 1024ULL : 1000ULL; + + if (bytes) + *rate = raw; + else + *rate = raw / 8ULL; + + return 0; +} diff --git a/lib/tc.h b/lib/tc.h new file mode 100644 index 0000000000..ec68e1f4cd --- /dev/null +++ b/lib/tc.h @@ -0,0 +1,151 @@ +/* + * Traffic Control (TC) main header + * Copyright (C) 2022 Shichu Yang + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _TC_H +#define _TC_H + +#include <zebra.h> +#include "stream.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TC_STR "Traffic Control\n" + +/* qdisc definitions */ + +/* qdisc kind (same as class kinds) */ +enum tc_qdisc_kind { + TC_QDISC_UNSPEC, + TC_QDISC_HTB, + TC_QDISC_NOQUEUE, +}; + +struct tc_qdisc_htb { + /* currently no members */ +}; + +struct tc_qdisc { + ifindex_t ifindex; + + enum tc_qdisc_kind kind; + union { + struct tc_qdisc_htb htb; + } u; +}; + +/* class definitions */ + +/* since classes share the same kinds of qdisc, duplicates omitted */ +struct tc_class_htb { + uint64_t rate; + uint64_t ceil; +}; + +struct tc_class { + ifindex_t ifindex; + uint32_t handle; + + enum tc_qdisc_kind kind; + union { + struct tc_class_htb htb; + } u; +}; + +/* filter definitions */ + +/* filter kinds */ +enum tc_filter_kind { + TC_FILTER_UNSPEC, + TC_FILTER_BPF, + TC_FILTER_FLOW, + TC_FILTER_FLOWER, + TC_FILTER_U32, +}; + +struct tc_bpf { + /* TODO: fill in */ +}; + +struct tc_flow { + /* TODO: fill in */ +}; + +struct tc_flower { + uint32_t classid; + +#define TC_FLOWER_IP_PROTOCOL (1 << 0) +#define TC_FLOWER_SRC_IP (1 << 1) +#define TC_FLOWER_DST_IP (1 << 2) +#define TC_FLOWER_SRC_PORT (1 << 3) +#define TC_FLOWER_DST_PORT (1 << 4) +#define TC_FLOWER_DSFIELD (1 << 5) + + uint32_t filter_bm; + + uint8_t ip_proto; + + struct prefix src_ip; + struct prefix dst_ip; + + uint16_t src_port_min; + uint16_t src_port_max; + uint16_t dst_port_min; + uint16_t dst_port_max; + + uint8_t dsfield; + uint8_t dsfield_mask; +}; + +struct tc_u32 { + /* TODO: fill in */ +}; + +struct tc_filter { + ifindex_t ifindex; + uint32_t handle; + + uint32_t priority; + uint16_t protocol; + + enum tc_filter_kind kind; + + union { + struct tc_bpf bpf; + struct tc_flow flow; + struct tc_flower flower; + struct tc_u32 u32; + } u; +}; + +extern int tc_getrate(const char *str, uint64_t *rate); + +extern int zapi_tc_qdisc_encode(uint8_t cmd, struct stream *s, + struct tc_qdisc *qdisc); +extern int zapi_tc_class_encode(uint8_t cmd, struct stream *s, + struct tc_class *class); +extern int zapi_tc_filter_encode(uint8_t cmd, struct stream *s, + struct tc_filter *filter); + +#ifdef __cplusplus +} +#endif + +#endif /* _TC_H */ @@ -528,6 +528,7 @@ void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *), static void vrf_terminate_single(struct vrf *vrf) { /* Clear configured flag and invoke delete. */ + vrf_disable(vrf); UNSET_FLAG(vrf->status, VRF_CONFIGURED); if_terminate(vrf); vrf_delete(vrf); diff --git a/lib/zclient.c b/lib/zclient.c index fd6eb7db0d..07c7e5aea8 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 731769abf7..584a42194d 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 { |
