diff options
author | Wesley Coakley <wcoakley@nvidia.com> | 2020-06-24 11:37:06 +0200 |
---|---|---|
committer | Wesley Coakley <wcoakley@nvidia.com> | 2020-07-15 18:59:36 +0200 |
commit | 116b86bdb9ecff4567b2a300e1cf8cf148b89103 (patch) | |
tree | cfc7803d5c8302397a8f2739f4968f22c66ec4f2 /pbrd | |
parent | pbrd, zebra, lib: DSCP / ECN-based PBR Matching (diff) | |
download | frr-116b86bdb9ecff4567b2a300e1cf8cf148b89103.tar.xz frr-116b86bdb9ecff4567b2a300e1cf8cf148b89103.zip |
pbrd: dscp interpret standard codepoints
Matching by dscp may now also be specified by its standard codepoint
(provided it has one), such as `cf0` or `af11`.
Signed-off-by: Wesley Coakley <wcoakley@nvidia.com>
Diffstat (limited to 'pbrd')
-rw-r--r-- | pbrd/pbr_map.c | 53 | ||||
-rw-r--r-- | pbrd/pbr_map.h | 2 | ||||
-rw-r--r-- | pbrd/pbr_vty.c | 46 |
3 files changed, 95 insertions, 6 deletions
diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c index 3a3bea349..2f801bd74 100644 --- a/pbrd/pbr_map.c +++ b/pbrd/pbr_map.c @@ -444,6 +444,59 @@ static void pbr_map_add_interfaces(struct pbr_map *pbrm) } } +/* Decodes a standardized DSCP into its representative value */ +uint8_t pbr_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; +} + struct pbr_map_sequence *pbrms_get(const char *name, uint32_t seqno) { struct pbr_map *pbrm; diff --git a/pbrd/pbr_map.h b/pbrd/pbr_map.h index fb8c6bf03..05b8d407d 100644 --- a/pbrd/pbr_map.h +++ b/pbrd/pbr_map.h @@ -169,6 +169,8 @@ extern void pbr_map_add_interface(struct pbr_map *pbrm, struct interface *ifp); extern void pbr_map_interface_delete(struct pbr_map *pbrm, struct interface *ifp); +extern uint8_t pbr_map_decode_dscp_enum(const char *name); + /* Update maps installed on interface */ extern void pbr_map_policy_interface_update(const struct interface *ifp, bool state_up); diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 947250323..37095625f 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -184,21 +184,57 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd, } DEFPY(pbr_map_match_dscp, pbr_map_match_dscp_cmd, - "[no] match dscp (0-63)$dscp", + "[no] match dscp DSCP$dscp", NO_STR "Match the rest of the command\n" "Match based on IP DSCP field\n" - "Differentiated Service Code Point\n") + "DSCP value (below 64) or standard codepoint name\n") { struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); + char dscpname[100]; + uint8_t rawDscp; + + /* Discriminate dscp enums (cs0, cs1 etc.) and numbers */ + bool isANumber = true; + 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) { + /* Refuse to install on overflow */ + vty_out(vty, "dscp (%s) must be less than 64\n", dscp); + return CMD_WARNING_CONFIG_FAILED; + } + rawDscp = dscpAsNum; + } else { + /* check dscp if it is an enum like cs0 */ + rawDscp = pbr_map_decode_dscp_enum(dscpname); + if (rawDscp > PBR_DSFIELD_DSCP) { + vty_out(vty, "Invalid dscp value: %s\n", dscpname); + return CMD_WARNING_CONFIG_FAILED; + } + } if (!no) { - if (((pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2) == dscp) + if (((pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2) == rawDscp) return CMD_SUCCESS; /* Set the DSCP bits of the DSField */ pbrms->dsfield = - (pbrms->dsfield & ~PBR_DSFIELD_DSCP) | (dscp << 2); + (pbrms->dsfield & ~PBR_DSFIELD_DSCP) | (rawDscp << 2); } else { pbrms->dsfield &= ~PBR_DSFIELD_DSCP; } @@ -614,8 +650,6 @@ static void vty_show_pbrms(struct vty *vty, if (pbrms->dsfield & PBR_DSFIELD_ECN) vty_out(vty, " ECN Match: %u\n", pbrms->dsfield & PBR_DSFIELD_ECN); - if (pbrms->dsfield) - vty_out(vty, " DSField Match: %u\n", (pbrms->dsfield)); if (pbrms->mark) vty_out(vty, " MARK Match: %u\n", pbrms->mark); |