Page MenuHomeVyOS Platform

0001-QPPB-DEMO-FRR.patch

Authored By
v.huti
Jul 14 2022, 1:59 PM
Size
24 KB
Referenced Files
None
Subscribers
None

0001-QPPB-DEMO-FRR.patch

From e8ea359a1775c8a2030ed16f819cabcbd4be154c Mon Sep 17 00:00:00 2001
From: Volodymyr Huti <[email protected]>
Date: Thu, 14 Jul 2022 16:55:55 +0300
Subject: [PATCH] QPPB DEMO (FRR)
---
bgpd/bgp_attr.c | 1 +
bgpd/bgp_attr.h | 2 +
bgpd/bgp_routemap.c | 29 +++++++
bgpd/bgp_zebra.c | 7 ++
include/linux/rtnetlink.h | 2 +
lib/routemap.c | 175 ++++++++++++++++++++++++++++++++++++++
lib/routemap.h | 28 ++++++
lib/routemap_cli.c | 39 +++++++++
lib/routemap_northbound.c | 53 ++++++++++++
lib/zclient.c | 4 +
lib/zclient.h | 3 +
yang/frr-route-map.yang | 15 ++++
zebra/rib.h | 3 +
zebra/rt_netlink.c | 10 +++
zebra/zapi_msg.c | 5 ++
zebra/zebra_dplane.c | 21 +++++
zebra/zebra_dplane.h | 2 +
zebra/zebra_rib.c | 2 +
zebra/zebra_vty.c | 18 ++++
19 files changed, 419 insertions(+)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index d57281a70..3b610d65e 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -961,6 +961,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin)
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
attr->tag = 0;
+ attr->dscp = 0;
attr->label_index = BGP_INVALID_LABEL_INDEX;
attr->label = MPLS_INVALID_LABEL;
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 01d993dab..913ba6d41 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -325,6 +325,8 @@ struct attr {
/* SR-TE Color */
uint32_t srte_color;
+ uint8_t dscp;
+
/* EVPN DF preference and algorithm for DF election on local ESs */
uint16_t df_pref;
uint8_t df_alg;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index c7f5e0433..739aed17a 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -119,6 +119,7 @@ o Cisco route-map
metric-type : Not yet
origin : Done
tag : Done
+ dscp : Done
weight : Done
table : Done
@@ -3053,6 +3054,30 @@ static const struct route_map_rule_cmd route_set_tag_cmd = {
route_map_rule_tag_free,
};
+/* Set dscp to object. object must be pointer to struct bgp_path_info */
+static enum route_map_cmd_result_t
+route_set_dscp(void *rule, const struct prefix *prefix, void *object)
+{
+ struct bgp_path_info *path;
+ uint8_t *rawDscp;
+
+ rawDscp = rule;
+ path = object;
+
+ /* Set dscp value */
+ path->attr->dscp = *rawDscp;
+
+ return RMAP_OKAY;
+}
+
+/* Route map commands for dscp set. */
+static const struct route_map_rule_cmd route_set_dscp_cmd = {
+ "dscp",
+ route_set_dscp,
+ route_map_rule_dscp_compile,
+ route_map_rule_dscp_free,
+};
+
/* Set label-index to object. object must be pointer to struct bgp_path_info */
static enum route_map_cmd_result_t
route_set_label_index(void *rule, const struct prefix *prefix, void *object)
@@ -6777,6 +6802,9 @@ void bgp_route_map_init(void)
route_map_set_tag_hook(generic_set_add);
route_map_no_set_tag_hook(generic_set_delete);
+ route_map_set_dscp_hook(generic_set_add);
+ route_map_no_set_dscp_hook(generic_set_delete);
+
route_map_install_match(&route_match_peer_cmd);
route_map_install_match(&route_match_alias_cmd);
route_map_install_match(&route_match_local_pref_cmd);
@@ -6835,6 +6863,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ecommunity_lb_cmd);
route_map_install_set(&route_set_ecommunity_none_cmd);
route_map_install_set(&route_set_tag_cmd);
+ route_map_install_set(&route_set_dscp_cmd);
route_map_install_set(&route_set_label_index_cmd);
install_element(RMAP_NODE, &match_peer_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 2c1d56172..1a9770ab2 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1274,6 +1274,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
uint64_t cum_bw = 0;
uint32_t nhg_id = 0;
bool is_add;
+ uint8_t dscp;
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance.
@@ -1315,6 +1316,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
}
tag = info->attr->tag;
+ dscp = info->attr->dscp;
/* If the route's source is EVPN, flag as such. */
is_evpn = is_route_parent_evpn(info);
@@ -1421,6 +1423,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
if (mpinfo == info) {
metric = mpinfo_cp->attr->med;
tag = mpinfo_cp->attr->tag;
+ dscp = mpinfo_cp->attr->dscp;
}
}
@@ -1550,6 +1553,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric;
+ if (dscp) {
+ SET_FLAG(api.message, ZAPI_MESSAGE_DSCP);
+ api.dscp = dscp;
+ }
if (tag) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index b15b72a26..5450e95e1 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -241,6 +241,7 @@ struct rtattr {
****/
struct rtmsg {
+ /* unsigned char rtm_dscp; */
unsigned char rtm_family;
unsigned char rtm_dst_len;
unsigned char rtm_src_len;
@@ -342,6 +343,7 @@ enum rt_scope_t {
#define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */
#define RTM_F_OFFLOAD 0x4000 /* route is offloaded */
#define RTM_F_TRAP 0x8000 /* route is trapping packets */
+#define RTM_F_DSCP 0x10000 /* route modifies the dscp mark */
#define RTM_F_OFFLOAD_FAILED 0x20000000 /* route offload failed, this value
* is chosen to avoid conflicts with
* other flags defined in
diff --git a/lib/routemap.c b/lib/routemap.c
index 722693ea2..387c91bf0 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -425,6 +425,24 @@ void route_map_no_set_tag_hook(int (*func)(struct route_map_index *index,
rmap_match_set_hook.no_set_tag = func;
}
+/* set dscp */
+void route_map_set_dscp_hook(int (*func)(struct route_map_index *index,
+ const char *command, const char *arg,
+ char *errmsg, size_t errmsg_len))
+{
+
+ rmap_match_set_hook.set_dscp = func;
+}
+
+/* no set dscp */
+void route_map_no_set_dscp_hook(int (*func)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ char *errmsg, size_t errmsg_len))
+{
+ rmap_match_set_hook.no_set_dscp = func;
+}
+
int generic_match_add(struct route_map_index *index,
const char *command, const char *arg,
route_map_event_t type,
@@ -3203,6 +3221,163 @@ void *route_map_rule_tag_compile(const char *arg)
return tag;
}
+/* Decodes a standardized DSCP into its representative value */
+uint8_t route_map_decode_dscp_enum(const char *name)
+{
+ /* Standard Differentiated Services Field Codepoints */
+ if (!strcmp(name, "cs0"))
+ return 0;
+ if (!strcmp(name, "cs1"))
+ return 8;
+ if (!strcmp(name, "cs2"))
+ return 16;
+ if (!strcmp(name, "cs3"))
+ return 24;
+ if (!strcmp(name, "cs4"))
+ return 32;
+ if (!strcmp(name, "cs5"))
+ return 40;
+ if (!strcmp(name, "cs6"))
+ return 48;
+ if (!strcmp(name, "cs7"))
+ return 56;
+ if (!strcmp(name, "af11"))
+ return 10;
+ if (!strcmp(name, "af12"))
+ return 12;
+ if (!strcmp(name, "af13"))
+ return 14;
+ if (!strcmp(name, "af21"))
+ return 18;
+ if (!strcmp(name, "af22"))
+ return 20;
+ if (!strcmp(name, "af23"))
+ return 22;
+ if (!strcmp(name, "af31"))
+ return 26;
+ if (!strcmp(name, "af32"))
+ return 28;
+ if (!strcmp(name, "af33"))
+ return 30;
+ if (!strcmp(name, "af41"))
+ return 34;
+ if (!strcmp(name, "af42"))
+ return 36;
+ if (!strcmp(name, "af43"))
+ return 38;
+ if (!strcmp(name, "ef"))
+ return 46;
+ if (!strcmp(name, "voice-admit"))
+ return 44;
+
+ /* No match? Error out */
+ return -1;
+}
+
+const char *route_map_dscp_enum_str(int dscp)
+{
+ /* Standard Differentiated Services Field Codepoints */
+ switch (dscp) {
+ case 0:
+ return "cs0";
+ case 8:
+ return "cs1";
+ case 16:
+ return "cs2";
+ case 24:
+ return "cs3";
+ case 32:
+ return "cs4";
+ case 40:
+ return "cs5";
+ case 48:
+ return "cs6";
+ case 56:
+ return "cs7";
+ case 10:
+ return "af11";
+ case 12:
+ return "af12";
+ case 14:
+ return "af13";
+ case 18:
+ return "af21";
+ case 20:
+ return "af22";
+ case 22:
+ return "af23";
+ case 26:
+ return "af31";
+ case 28:
+ return "af32";
+ case 30:
+ return "af33";
+ case 34:
+ return "af41";
+ case 36:
+ return "af42";
+ case 38:
+ return "af43";
+ case 46:
+ return "ef";
+ case 44:
+ return "voice-admit";
+ default:
+ return NULL;
+ }
+}
+
+#define PBR_DSFIELD_DSCP (0xfc) /* Upper 6 bits of DS field: DSCP */
+/* Discriminate dscp enums (cs0, cs1 etc.) and numbers */
+void *route_map_rule_dscp_compile(const char *dscp)
+{
+ char dscpname[100];
+ bool isANumber = true;
+ uint8_t *rawDscp, tmpDscp;
+
+ for (int i = 0; i < (int)strlen(dscp); i++) {
+ /* Letters are not numbers */
+ if (!isdigit(dscp[i]))
+ isANumber = false;
+
+ /* Lowercase the dscp enum (if needed) */
+ if (isupper(dscp[i]))
+ dscpname[i] = tolower(dscp[i]);
+ else
+ dscpname[i] = dscp[i];
+ }
+ dscpname[strlen(dscp)] = '\0';
+
+ if (isANumber) {
+ /* dscp passed is a regular number */
+ long dscpAsNum = strtol(dscp, NULL, 0);
+ if (dscpAsNum > PBR_DSFIELD_DSCP >> 2) {
+ zlog_debug("dscp (%s) must be less than 64\n", dscp);
+ return NULL;
+ }
+
+ rawDscp = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*rawDscp));
+ *rawDscp = dscpAsNum;
+ } else {
+ /* check dscp if it is an enum like cs0 */
+ tmpDscp = route_map_decode_dscp_enum(dscpname);
+ if (tmpDscp > PBR_DSFIELD_DSCP) {
+ zlog_debug("Invalid dscp value: %s\n", dscpname);
+ return NULL;
+ }
+ rawDscp = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*rawDscp));
+ *rawDscp = tmpDscp;
+ }
+
+ *rawDscp = (*rawDscp << 2);
+ return rawDscp;
+}
+
+void route_map_rule_dscp_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
void route_map_rule_tag_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
diff --git a/lib/routemap.h b/lib/routemap.h
index 13dafe684..123fd0d04 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -322,6 +322,7 @@ DECLARE_QOBJ_TYPE(route_map);
#define IS_SET_METRIC(A) \
(strmatch(A, "frr-route-map:set-metric"))
#define IS_SET_TAG(A) (strmatch(A, "frr-route-map:set-tag"))
+#define IS_SET_DSCP(A) (strmatch(A, "frr-route-map:set-dscp"))
#define IS_SET_SR_TE_COLOR(A) \
(strmatch(A, "frr-route-map:set-sr-te-color"))
/* Zebra route-map set actions */
@@ -703,8 +704,25 @@ extern void route_map_no_set_tag_hook(int (*func)(struct route_map_index *index,
char *errmsg,
size_t errmsg_len));
+/* set dscp */
+extern void route_map_set_dscp_hook(int (*func)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ char *errmsg,
+ size_t errmsg_len));
+/* no set dscp */
+extern void route_map_no_set_dscp_hook(int (*func)(struct route_map_index *index,
+ const char *command,
+ const char *arg,
+ char *errmsg,
+ size_t errmsg_len));
+
extern void *route_map_rule_tag_compile(const char *arg);
extern void route_map_rule_tag_free(void *rule);
+extern uint8_t route_map_decode_dscp_enum(const char *name);
+extern const char *route_map_dscp_enum_str(int dscp);
+extern void *route_map_rule_dscp_compile(const char *dscp);
+extern void route_map_rule_dscp_free(void *dscp);
/* Increment the route-map used counter */
extern void route_map_counter_increment(struct route_map *map);
@@ -936,6 +954,16 @@ struct route_map_match_set_hooks {
int (*no_set_tag)(struct route_map_index *index,
const char *command, const char *arg,
char *errmsg, size_t errmsg_len);
+
+ /* set dscp */
+ int (*set_dscp)(struct route_map_index *index,
+ const char *command, const char *arg,
+ char *errmsg, size_t errmsg_len);
+
+ /* no set dscp */
+ int (*no_set_dscp)(struct route_map_index *index,
+ const char *command, const char *arg,
+ char *errmsg, size_t errmsg_len);
};
extern struct route_map_match_set_hooks rmap_match_set_hook;
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index ff98a14c4..9ec415bb5 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -934,6 +934,39 @@ DEFPY_YANG(
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG(
+ set_dscp, set_dscp_cmd,
+ "set dscp DSCP$dscp",
+ SET_STR
+ "DSCP value for routing protocol\n"
+ "DSCP value\n")
+{
+ const char *xpath = "./set-action[action='frr-route-map:set-dscp']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/dscp",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, dscp);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_set_dscp, no_set_dscp_cmd,
+ "no set dscp [OPTVAL]",
+ NO_STR
+ SET_STR
+ "DSCP value for routing protocol\n"
+ "DSCP value\n")
+{
+ const char *xpath = "./set-action[action='frr-route-map:set-dscp']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFUN_YANG (set_srte_color,
set_srte_color_cmd,
"set sr-te color (1-4294967295)",
@@ -1025,6 +1058,9 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
} else if (IS_SET_TAG(action)) {
vty_out(vty, " set tag %s\n",
yang_dnode_get_string(dnode, "./rmap-set-action/tag"));
+ } else if (IS_SET_DSCP(action)) {
+ vty_out(vty, " set dscp %s\n",
+ yang_dnode_get_string(dnode, "./rmap-set-action/dscp"));
} else if (IS_SET_SR_TE_COLOR(action)) {
vty_out(vty, " set sr-te color %s\n",
yang_dnode_get_string(dnode,
@@ -1555,6 +1591,9 @@ void route_map_cli_init(void)
install_element(RMAP_NODE, &set_tag_cmd);
install_element(RMAP_NODE, &no_set_tag_cmd);
+ install_element(RMAP_NODE, &set_dscp_cmd);
+ install_element(RMAP_NODE, &no_set_dscp_cmd);
+
install_element(RMAP_NODE, &set_srte_color_cmd);
install_element(RMAP_NODE, &no_set_srte_color_cmd);
}
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 51b879959..bfbbc8252 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -1193,6 +1193,52 @@ lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args *args)
return lib_route_map_entry_set_destroy(args);
}
+/*
+ * XPath: /frr-route-map:lib/route-map/entry/set-action/dscp
+ */
+static int
+lib_route_map_entry_set_action_dscp_modify(struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *dscp;
+ int rv;
+
+ /*
+ * NOTE: validate if 'action' is 'dscp', currently it is not
+ * necessary because this is the only implemented action. Other
+ * actions might have different validations.
+ */
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ /* Check for hook function. */
+ if (rmap_match_set_hook.set_dscp == NULL)
+ return NB_OK;
+
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ dscp = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_shook = rmap_match_set_hook.no_set_dscp;
+ rhc->rhc_rule = "dscp";
+
+ rv = rmap_match_set_hook.set_dscp(rhc->rhc_rmi, "dscp", dscp,
+ args->errmsg, args->errmsg_len);
+ if (rv != CMD_SUCCESS) {
+ rhc->rhc_shook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ return NB_OK;
+}
+
+static int
+lib_route_map_entry_set_action_dscp_destroy(struct nb_cb_destroy_args *args)
+{
+ return lib_route_map_entry_set_destroy(args);
+}
+
/*
* XPath: /frr-route-map:lib/route-map/entry/set-action/policy
*/
@@ -1424,6 +1470,13 @@ const struct frr_yang_module_info frr_route_map_info = {
.destroy = lib_route_map_entry_set_action_tag_destroy,
}
},
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/dscp",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_dscp_modify,
+ .destroy = lib_route_map_entry_set_action_dscp_destroy,
+ }
+ },
{
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/policy",
.cbs = {
diff --git a/lib/zclient.c b/lib/zclient.c
index a933b6bb2..612d35ce8 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1324,6 +1324,8 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
stream_putc(s, api->distance);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
stream_putl(s, api->metric);
+ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DSCP))
+ stream_putl(s, api->dscp);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
stream_putl(s, api->tag);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
@@ -1567,6 +1569,8 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETC(s, api->distance);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC))
STREAM_GETL(s, api->metric);
+ if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DSCP))
+ STREAM_GETL(s, api->dscp);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG))
STREAM_GETL(s, api->tag);
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU))
diff --git a/lib/zclient.h b/lib/zclient.h
index 9756923a6..d785a6518 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -389,6 +389,7 @@ extern int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS);
#define ZAPI_MESSAGE_TABLEID 0x0100
#define ZAPI_MESSAGE_SRTE 0x0200
#define ZAPI_MESSAGE_OPAQUE 0x0400
+#define ZAPI_MESSAGE_DSCP 0x0800
#define ZSERV_VERSION 6
/* Zserv protocol message header */
@@ -562,6 +563,8 @@ struct zapi_route {
uint32_t metric;
+ uint32_t dscp;
+
route_tag_t tag;
uint32_t mtu;
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
index 1e8c04bc6..b0e479dd2 100644
--- a/yang/frr-route-map.yang
+++ b/yang/frr-route-map.yang
@@ -165,6 +165,12 @@ module frr-route-map {
"Set tag";
}
+ identity set-dscp {
+ base rmap-set-type;
+ description
+ "Set dscp";
+ }
+
identity set-sr-te-color {
base rmap-set-type;
description
@@ -356,6 +362,15 @@ module frr-route-map {
}
}
+ case set-dscp {
+ when "derived-from-or-self(../action, 'set-dscp')";
+ leaf dscp {
+ type string;
+ description
+ "Dscp value";
+ }
+ }
+
case set-sr-te-color {
when "derived-from-or-self(../action, 'set-sr-te-color')";
leaf policy {
diff --git a/zebra/rib.h b/zebra/rib.h
index 60092c963..278beccef 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -131,6 +131,9 @@ struct route_entry {
/* Metric */
uint32_t metric;
+ /* DSCP */
+ uint32_t dscp;
+
/* MTU */
uint32_t mtu;
uint32_t nexthop_mtu;
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 93b2d9467..7b09349b5 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -694,6 +694,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
uint8_t distance = 0;
route_tag_t tag = 0;
uint32_t nhe_id = 0;
+ uint8_t dscp = 0;
void *dest = NULL;
void *gate = NULL;
@@ -782,6 +783,11 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
flags |= ZEBRA_FLAG_OFFLOADED;
if (rtm->rtm_flags & RTM_F_OFFLOAD_FAILED)
flags |= ZEBRA_FLAG_OFFLOAD_FAILED;
+#if 0
+ if (rtm->rtm_flags & RTM_F_DSCP) {
+ zlog_debug("QQQ DSCP DETECTED %d", dscp);
+ }
+#endif
/* Route which inserted by Zebra. */
if (selfroute) {
@@ -947,6 +953,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
re->uptime = monotime(NULL);
re->tag = tag;
re->nhe_id = nhe_id;
+ re->dscp = 0;
if (!nhe_id) {
uint8_t nhop_num;
@@ -1959,6 +1966,9 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
req->r.rtm_dst_len = p->prefixlen;
req->r.rtm_src_len = src_p ? src_p->prefixlen : 0;
req->r.rtm_scope = RT_SCOPE_UNIVERSE;
+ req->r.rtm_tos = dplane_ctx_get_dscp(ctx);
+ if (req->r.rtm_tos)
+ req->r.rtm_flags |= RTM_F_DSCP;
if (cmd == RTM_DELROUTE)
req->r.rtm_protocol = zebra2proto(dplane_ctx_get_old_type(ctx));
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 9a30c2b78..9f2bc027b 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -631,6 +631,8 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
api.distance = re->distance;
SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
api.metric = re->metric;
+ SET_FLAG(api.message, ZAPI_MESSAGE_DSCP);
+ api.dscp = re->dscp;
if (re->tag) {
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = re->tag;
@@ -2111,6 +2113,9 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
re->tag = api.tag;
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU))
re->mtu = api.mtu;
+ if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DSCP))
+ re->dscp = api.dscp;
+
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_OPAQUE)) {
re->opaque =
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 0da44e3c4..e645d07be 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -124,6 +124,9 @@ struct dplane_route_info {
uint32_t zd_metric;
uint32_t zd_old_metric;
+ uint32_t zd_dscp;
+ uint32_t zd_old_dscp;
+
uint16_t zd_instance;
uint16_t zd_old_instance;
@@ -1376,6 +1379,21 @@ uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_old_metric;
}
+
+uint32_t dplane_ctx_get_dscp(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rinfo.zd_dscp;
+}
+
+uint32_t dplane_ctx_get_old_dscp(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rinfo.zd_old_dscp;
+}
+
uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -2508,6 +2526,8 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
ctx->u.rinfo.zd_metric = re->metric;
ctx->u.rinfo.zd_old_metric = re->metric;
+ ctx->u.rinfo.zd_dscp = re->dscp;
+ ctx->u.rinfo.zd_old_dscp = re->dscp;
ctx->zd_vrf_id = re->vrf_id;
ctx->u.rinfo.zd_mtu = re->mtu;
ctx->u.rinfo.zd_nexthop_mtu = re->nexthop_mtu;
@@ -3243,6 +3263,7 @@ dplane_route_update_internal(struct route_node *rn,
ctx->u.rinfo.zd_old_instance = old_re->instance;
ctx->u.rinfo.zd_old_distance = old_re->distance;
ctx->u.rinfo.zd_old_metric = old_re->metric;
+ ctx->u.rinfo.zd_old_dscp = old_re->dscp;
ctx->u.rinfo.nhe.old_id = old_re->nhe->id;
#ifndef HAVE_NETLINK
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 334d440a2..705fb615e 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -372,6 +372,8 @@ void dplane_ctx_set_instance(struct zebra_dplane_ctx *ctx, uint16_t instance);
uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx);
+uint32_t dplane_ctx_get_dscp(const struct zebra_dplane_ctx *ctx);
+uint32_t dplane_ctx_get_old_dscp(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_nh_mtu(const struct zebra_dplane_ctx *ctx);
uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 680128001..b6faafc1e 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -3820,6 +3820,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
struct route_entry *re = NULL;
struct nexthop *nexthop = NULL;
struct nexthop_group *ng = NULL;
+ int dscp = 0;
/* Allocate new route_entry structure. */
re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
@@ -3834,6 +3835,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
re->uptime = monotime(NULL);
re->tag = tag;
re->nhe_id = nhe_id;
+ re->dscp = dscp;
/* If the owner of the route supplies a shared nexthop-group id,
* we'll use that. Otherwise, pass the nexthop along directly.
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 3756f8153..4bf724456 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -595,6 +595,16 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
}
}
+static char *my_itoa(int num, char *str)
+{
+ if(str == NULL)
+ {
+ return NULL;
+ }
+ sprintf(str, "%d", num);
+ return str;
+}
+
/*
* Helper for nexthop output, used in the 'show ip route' path
*/
@@ -708,6 +718,14 @@ static void show_route_nexthop_helper(struct vty *vty,
if (nexthop->weight)
vty_out(vty, ", weight %u", nexthop->weight);
+
+ uint32_t dscp = re->dscp >> 2;
+ const char *dscp_name = route_map_dscp_enum_str(dscp);
+ if (dscp_name)
+ memcpy(buf, dscp_name, sizeof(buf));
+ else
+ my_itoa(dscp, buf);
+ vty_out(vty, ", dscp %s", buf);
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
--
2.25.1

File Metadata

Mime Type
text/x-diff
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2b/ca/7270247ad8266332a4c137df51a2
Default Alt Text
0001-QPPB-DEMO-FRR.patch (24 KB)

Event Timeline