Merge pull request #9742 from elimbaum/add-vlan-actions

pbrd: add vlan actions to vty
This commit is contained in:
Jafar Al-Gharaibeh 2021-10-23 00:06:16 -05:00 committed by GitHub
commit 63da89db77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 205 additions and 6 deletions

View File

@ -154,6 +154,31 @@ end destination.
(ECN) field in the IP header; if this value matches then forward the packet
according to the nexthop(s) specified.
.. clicmd:: set queue-id (1-65535)
Set the egress port queue identifier for matched packets. The Linux Kernel
provider does not currently support packet mangling, so this field will be
ignored unless another provider is used.
.. clicmd:: set pcp (0-7)
Set the 802.1Q priority code point (PCP) for matched packets. A PCP of zero
is the defaul (nominally, "best effort"). The Linux Kernel provider does not
currently support packet mangling, so this field will be ignored unless
another provider is used.
.. clicmd:: set vlan (1-4094)
Set the VLAN tag for matched packets. Identifiers 0 and 4095 are reserved.
The Linux Kernel provider does not currently support packet mangling, so
this field will be ignored unless another provider is used.
.. clicmd:: strip vlan
Strip inner vlan tags from matched packets. The Linux Kernel provider does not currently support packet mangling, so this field will be ignored unless another provider is used. It is invalid to specify both a `strip` and `set
vlan` action.
.. clicmd:: set nexthop-group NAME
Use the nexthop-group NAME as the place to forward packets when the match

View File

@ -50,7 +50,7 @@ struct pbr_filter {
#define PBR_FILTER_SRC_PORT_RANGE (1 << 6)
#define PBR_FILTER_DST_PORT_RANGE (1 << 7)
#define PBR_FILTER_DSFIELD (1 << 8)
#define PBR_FILTER_IP_PROTOCOL (1 << 9)
#define PBR_FILTER_IP_PROTOCOL (1 << 9)
#define PBR_DSFIELD_DSCP (0xfc) /* Upper 6 bits of DS field: DSCP */
#define PBR_DSFIELD_ECN (0x03) /* Lower 2 bits of DS field: BCN */
@ -83,6 +83,13 @@ struct pbr_filter {
* the user criteria may directly point to a table too.
*/
struct pbr_action {
/* VLAN */
uint8_t pcp;
uint16_t vlan_id;
uint16_t vlan_flags;
uint32_t queue_id;
uint32_t table;
};

View File

@ -178,9 +178,9 @@ static void pbr_map_pbrms_uninstall(struct pbr_map_sequence *pbrms)
}
static const char *const pbr_map_reason_str[] = {
"Invalid NH-group", "Invalid NH", "No Nexthops",
"Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
"Deleting Sequence",
"Invalid NH-group", "Invalid NH", "No Nexthops",
"Both NH and NH-Group", "Invalid Src or Dst", "Invalid VRF",
"Both VLAN Set and Strip", "Deleting Sequence",
};
void pbr_map_reason_string(unsigned int reason, char *buf, int size)
@ -539,6 +539,13 @@ struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno)
pbrms->seqno = seqno;
pbrms->ruleno = pbr_nht_get_next_rule(seqno);
pbrms->parent = pbrm;
pbrms->action_vlan_id = 0;
pbrms->action_vlan_flags = 0;
pbrms->action_pcp = 0;
pbrms->action_queue_id = PBR_MAP_UNDEFINED_QUEUE_ID;
pbrms->reason =
PBR_MAP_INVALID_EMPTY |
PBR_MAP_INVALID_NO_NEXTHOPS;
@ -601,10 +608,28 @@ pbr_map_sequence_check_nexthops_valid(struct pbr_map_sequence *pbrms)
static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
{
if (!pbrms->src && !pbrms->dst && !pbrms->mark && !pbrms->dsfield)
if (!pbrms->src && !pbrms->dst && !pbrms->mark && !pbrms->dsfield
&& !pbrms->action_vlan_id && !pbrms->action_vlan_flags
&& !pbrms->action_pcp
&& pbrms->action_queue_id == PBR_MAP_UNDEFINED_QUEUE_ID)
pbrms->reason |= PBR_MAP_INVALID_EMPTY;
}
static void pbr_map_sequence_check_vlan_actions(struct pbr_map_sequence *pbrms)
{
/* The set vlan tag action does the following:
* 1. If the frame is untagged, it tags the frame with the
* configured VLAN ID.
* 2. If the frame is tagged, if replaces the tag.
*
* The strip vlan action removes any inner tag, so it is invalid to
* specify both a set and strip action.
*/
if ((pbrms->action_vlan_id != 0) && (pbrms->action_vlan_flags != 0))
pbrms->reason |= PBR_MAP_INVALID_SET_STRIP_VLAN;
}
/*
* Checks to see if we think that the pbmrs is valid. If we think
* the config is valid return true.
@ -612,7 +637,7 @@ static void pbr_map_sequence_check_not_empty(struct pbr_map_sequence *pbrms)
static void pbr_map_sequence_check_valid(struct pbr_map_sequence *pbrms)
{
pbr_map_sequence_check_nexthops_valid(pbrms);
pbr_map_sequence_check_vlan_actions(pbrms);
pbr_map_sequence_check_not_empty(pbrms);
}

View File

@ -103,6 +103,17 @@ struct pbr_map_sequence {
uint8_t dsfield;
uint32_t mark;
/*
* Actions
*/
uint8_t action_pcp;
uint8_t action_vlan_id;
#define PBR_MAP_STRIP_INNER_ANY (1 << 0)
uint8_t action_vlan_flags;
#define PBR_MAP_UNDEFINED_QUEUE_ID 0
uint32_t action_queue_id;
/*
* Family of the src/dst. Needed when deleting since we clear them
*/
@ -158,6 +169,7 @@ struct pbr_map_sequence {
#define PBR_MAP_INVALID_BOTH_NHANDGRP (1 << 3)
#define PBR_MAP_INVALID_EMPTY (1 << 4)
#define PBR_MAP_INVALID_VRF (1 << 5)
#define PBR_MAP_INVALID_SET_STRIP_VLAN (1 << 6)
uint64_t reason;
QOBJ_FIELDS;

View File

@ -407,6 +407,82 @@ static void pbrms_clear_set_config(struct pbr_map_sequence *pbrms)
pbrms->nhs_installed = false;
}
DEFPY(pbr_map_action_queue_id, pbr_map_action_queue_id_cmd,
"[no] set queue-id <(1-65535)$queue_id>",
NO_STR
"Set the rest of the command\n"
"Set based on egress port queue id\n"
"A valid value in range 1..65535 \n")
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
if (!no)
pbrms->action_queue_id = queue_id;
else if ((uint32_t)queue_id == pbrms->action_queue_id)
pbrms->action_queue_id = PBR_MAP_UNDEFINED_QUEUE_ID;
pbr_map_check(pbrms, true);
return CMD_SUCCESS;
}
DEFPY(pbr_map_action_pcp, pbr_map_action_pcp_cmd, "[no] set pcp <(0-7)$pcp>",
NO_STR
"Set the rest of the command\n"
"Set based on 802.1p Priority Code Point (PCP) value\n"
"A valid value in range 0..7\n")
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
if (!no)
pbrms->action_pcp = pcp;
else if (pcp == pbrms->action_pcp)
pbrms->action_pcp = 0;
pbr_map_check(pbrms, true);
return CMD_SUCCESS;
}
DEFPY(pbr_map_action_vlan_id, pbr_map_action_vlan_id_cmd,
"[no] set vlan <(1-4094)$vlan_id>",
NO_STR
"Set the rest of the command\n"
"Set action for VLAN tagging\n"
"A valid value in range 1..4094\n")
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
if (!no)
pbrms->action_vlan_id = vlan_id;
else if (pbrms->action_vlan_id == vlan_id)
pbrms->action_vlan_id = 0;
pbr_map_check(pbrms, true);
return CMD_SUCCESS;
}
DEFPY(pbr_map_action_strip_vlan, pbr_map_action_strip_vlan_cmd,
"[no] strip vlan",
NO_STR
"Strip the vlan tags from frame\n"
"Strip any inner vlan tag \n")
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
if (!no)
pbrms->action_vlan_flags = PBR_MAP_STRIP_INNER_ANY;
else
pbrms->action_vlan_flags = 0;
pbr_map_check(pbrms, true);
return CMD_SUCCESS;
}
DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
"set nexthop-group NHGNAME$name",
"Set for the PBR-MAP\n"
@ -764,6 +840,18 @@ static void vty_show_pbrms(struct vty *vty,
if (pbrms->mark)
vty_out(vty, " MARK Match: %u\n", pbrms->mark);
if (pbrms->action_queue_id != PBR_MAP_UNDEFINED_QUEUE_ID)
vty_out(vty, " Set Queue ID %u\n",
pbrms->action_queue_id);
if (pbrms->action_vlan_id != 0)
vty_out(vty, " Set VLAN ID %u\n", pbrms->action_vlan_id);
if (pbrms->action_vlan_flags == PBR_MAP_STRIP_INNER_ANY)
vty_out(vty, " Strip VLAN ID\n");
if (pbrms->action_pcp)
vty_out(vty, " Set PCP %u\n", pbrms->action_pcp);
if (pbrms->nhgrp_name) {
vty_out(vty, " Nexthop-Group: %s\n", pbrms->nhgrp_name);
@ -1170,6 +1258,19 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty,
if (pbrms->mark)
vty_out(vty, " match mark %u\n", pbrms->mark);
if (pbrms->action_queue_id != PBR_MAP_UNDEFINED_QUEUE_ID)
vty_out(vty, " set queue-id %d\n", pbrms->action_queue_id);
if (pbrms->action_pcp)
vty_out(vty, " set pcp %d\n", pbrms->action_pcp);
if (pbrms->action_vlan_id)
vty_out(vty, " set vlan %u\n", pbrms->action_vlan_id);
if (pbrms->action_vlan_flags == PBR_MAP_STRIP_INNER_ANY)
vty_out(vty, " strip vlan any\n");
if (pbrms->vrf_unchanged)
vty_out(vty, " set vrf unchanged\n");
@ -1257,6 +1358,10 @@ void pbr_vty_init(void)
install_element(PBRMAP_NODE, &pbr_map_match_dscp_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_ecn_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
install_element(PBRMAP_NODE, &pbr_map_action_queue_id_cmd);
install_element(PBRMAP_NODE, &pbr_map_action_strip_vlan_cmd);
install_element(PBRMAP_NODE, &pbr_map_action_vlan_id_cmd);
install_element(PBRMAP_NODE, &pbr_map_action_pcp_cmd);
install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
install_element(PBRMAP_NODE, &no_pbr_map_nexthop_group_cmd);
install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);

View File

@ -542,6 +542,12 @@ static void pbr_encode_pbr_map_sequence(struct stream *s,
stream_putc(s, pbrms->dsfield);
stream_putl(s, pbrms->mark);
stream_putl(s, pbrms->action_queue_id);
stream_putw(s, pbrms->action_vlan_id);
stream_putw(s, pbrms->action_vlan_flags);
stream_putw(s, pbrms->action_pcp);
if (pbrms->vrf_unchanged || pbrms->vrf_lookup)
pbr_encode_pbr_map_sequence_vrf(s, pbrms, ifp);
else if (pbrms->nhgrp_name)

View File

@ -3190,6 +3190,12 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
STREAM_GETW(s, zpr.rule.filter.dst_port);
STREAM_GETC(s, zpr.rule.filter.dsfield);
STREAM_GETL(s, zpr.rule.filter.fwmark);
STREAM_GETL(s, zpr.rule.action.queue_id);
STREAM_GETW(s, zpr.rule.action.vlan_id);
STREAM_GETW(s, zpr.rule.action.vlan_flags);
STREAM_GETW(s, zpr.rule.action.pcp);
STREAM_GETL(s, zpr.rule.action.table);
STREAM_GET(ifname, s, INTERFACE_NAMSIZ);

View File

@ -261,6 +261,13 @@ struct dplane_ctx_rule {
struct prefix src_ip;
struct prefix dst_ip;
uint8_t ip_proto;
uint8_t action_pcp;
uint16_t action_vlan_id;
uint16_t action_vlan_flags;
uint32_t action_queue_id;
char ifname[INTERFACE_NAMSIZ + 1];
};
@ -2770,6 +2777,12 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule,
dplane_rule->ip_proto = rule->rule.filter.ip_proto;
prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
dplane_rule->action_pcp = rule->rule.action.pcp;
dplane_rule->action_vlan_flags = rule->rule.action.vlan_flags;
dplane_rule->action_vlan_id = rule->rule.action.vlan_id;
dplane_rule->action_queue_id = rule->rule.action.queue_id;
strlcpy(dplane_rule->ifname, rule->ifname, INTERFACE_NAMSIZ);
}