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
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)