Skip to content

Commit

Permalink
bgp, lib, yang: Extend route-map to support the DSCP tag
Browse files Browse the repository at this point in the history
Signed-off-by: Volodymyr Huti <[email protected]>
  • Loading branch information
Volodymyr Huti committed Oct 31, 2023
1 parent 4e1f4a4 commit 751061b
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 2 deletions.
1 change: 1 addition & 0 deletions bgpd/bgp_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,7 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
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);
Expand Down
3 changes: 3 additions & 0 deletions bgpd/bgp_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ struct attr {
/* SR-TE Color */
uint32_t srte_color;

/* DSCP tag, used by the QPPB plugin */
uint8_t dscp;

/* EVPN DF preference and algorithm for DF election on local ESs */
uint16_t df_pref;
uint8_t df_alg;
Expand Down
15 changes: 14 additions & 1 deletion bgpd/bgp_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "stream.h"
#include "filter.h"
#include "log.h"
#include "dscp.h"
#include "routemap.h"
#include "buffer.h"
#include "sockunion.h"
Expand Down Expand Up @@ -10104,7 +10105,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object *json_peer = NULL;
json_object *json_string = NULL;
json_object *json_adv_to = NULL;
int first = 0;
int first = 0, dscp = attr->dscp >> 2;
struct listnode *node, *nnode;
struct peer *peer;
bool addpath_capable;
Expand Down Expand Up @@ -10776,6 +10777,18 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
}

/* XXX: on Cisco
* R1# sh ip cef 5.5.0.0 de
* 5.5.0.0/24, epoch 0
* QOS: Precedence critical (5)
* recursive via ...
* nexthop ... iface
*/
if (dscp) {
vty_out(vty, " QOS: Precedence %s (%d)\n",
dscp_enum_str(dscp), dscp);
}

/* Line 5 display Extended-community */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
if (json_paths) {
Expand Down
29 changes: 29 additions & 0 deletions bgpd/bgp_routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ o Cisco route-map
metric-type : Not yet
origin : Done
tag : Done
dscp : Done
weight : Done
table : Done
Expand Down Expand Up @@ -3549,6 +3550,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)
Expand Down Expand Up @@ -7796,6 +7821,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);
Expand Down Expand Up @@ -7859,6 +7887,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ecommunity_color_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);
route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);

Expand Down
10 changes: 9 additions & 1 deletion bgpd/bgp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
uint32_t ttl = 0;
uint32_t bos = 0;
uint32_t exp = 0;
uint8_t dscp;

/*
* BGP is installing this route and bgp has been configured
Expand Down Expand Up @@ -1306,6 +1307,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
}

tag = info->attr->tag;
dscp = info->attr->dscp;

if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED
|| info->sub_type == BGP_ROUTE_AGGREGATE) {
Expand Down Expand Up @@ -1404,11 +1406,17 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
p, mpinfo_cp))
continue;

/* metric/tag is only allowed to be
/* metric/tag/dscp is only allowed to be
* overridden on 1st nexthop */
if (mpinfo == info) {
metric = mpinfo_cp->attr->med;
tag = mpinfo_cp->attr->tag;
/* used by hook from the QPPB plugin */
dscp = mpinfo_cp->attr->dscp;
/* expose value back to CLI `show bgp ipv4 nh`
* displayed by route_vty_out_detail()`
*/
mpinfo->attr->dscp = dscp;
}
}

Expand Down
46 changes: 46 additions & 0 deletions lib/routemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "table.h"
#include "json.h"
#include "jhash.h"
#include "dscp.h"

#include "lib/routemap_clippy.c"

Expand Down Expand Up @@ -446,6 +447,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,
Expand Down Expand Up @@ -3250,6 +3269,33 @@ void *route_map_rule_tag_compile(const char *arg)
return tag;
}

void *route_map_rule_dscp_compile(const char *dscp)
{
unsigned long ul_dscp;
char *pend = NULL;
uint8_t *shifted_dscp;

assert(dscp);
ul_dscp = strtoul(dscp, &pend, 0);
if (pend && *pend)
ul_dscp = dscp_decode_enum(dscp);

if (ul_dscp > (DSFIELD_DSCP >> 2)) {
zlog_err("Invalid dscp value: %s%s", dscp,
((pend && *pend) ? "" : " (numeric value must be in range 0-63)"));
return NULL;
}

shifted_dscp = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*shifted_dscp));
*shifted_dscp = (ul_dscp << 2) & DSFIELD_DSCP;
return shifted_dscp;
}

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);
Expand Down
23 changes: 23 additions & 0 deletions lib/routemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ DECLARE_QOBJ_TYPE(route_map);
#define IS_SET_MIN_METRIC(A) (strmatch(A, "frr-route-map:set-min-metric"))
#define IS_SET_MAX_METRIC(A) (strmatch(A, "frr-route-map:set-max-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 */
Expand Down Expand Up @@ -724,8 +725,22 @@ 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);
Expand Down Expand Up @@ -976,6 +991,14 @@ 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;
Expand Down
39 changes: 39 additions & 0 deletions lib/routemap_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,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)",
Expand Down Expand Up @@ -1103,6 +1136,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,
Expand Down Expand Up @@ -1669,6 +1705,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);
}
53 changes: 53 additions & 0 deletions lib/routemap_northbound.c
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,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
*/
Expand Down Expand Up @@ -1537,6 +1583,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 = {
Expand Down
Loading

0 comments on commit 751061b

Please sign in to comment.