diff options
Diffstat (limited to 'pbrd/pbr_vty.c')
| -rw-r--r-- | pbrd/pbr_vty.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index cd9096cbc8..a73d885ea6 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -183,6 +183,91 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd, return CMD_SUCCESS; } +DEFPY(pbr_map_match_dscp, pbr_map_match_dscp_cmd, + "[no] match dscp DSCP$dscp", + NO_STR + "Match the rest of the command\n" + "Match based on IP DSCP field\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) == rawDscp) + return CMD_SUCCESS; + + /* Set the DSCP bits of the DSField */ + pbrms->dsfield = + (pbrms->dsfield & ~PBR_DSFIELD_DSCP) | (rawDscp << 2); + } else { + pbrms->dsfield &= ~PBR_DSFIELD_DSCP; + } + + pbr_map_check(pbrms, true); + + return CMD_SUCCESS; +} + +DEFPY(pbr_map_match_ecn, pbr_map_match_ecn_cmd, + "[no] match ecn (0-3)$ecn", + NO_STR + "Match the rest of the command\n" + "Match based on IP ECN field\n" + "Explicit Congestion Notification\n") +{ + struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence); + + if (!no) { + if ((pbrms->dsfield & PBR_DSFIELD_ECN) == ecn) + return CMD_SUCCESS; + + /* Set the ECN bits of the DSField */ + pbrms->dsfield = (pbrms->dsfield & ~PBR_DSFIELD_ECN) | ecn; + } else { + pbrms->dsfield &= ~PBR_DSFIELD_ECN; + } + + pbr_map_check(pbrms, true); + + return CMD_SUCCESS; +} + DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd, "[no] match mark (1-4294967295)$mark", NO_STR @@ -559,6 +644,12 @@ static void vty_show_pbrms(struct vty *vty, if (pbrms->dst) vty_out(vty, " DST Match: %s\n", prefix2str(pbrms->dst, buf, sizeof(buf))); + if (pbrms->dsfield & PBR_DSFIELD_DSCP) + vty_out(vty, " DSCP Match: %u\n", + (pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2); + if (pbrms->dsfield & PBR_DSFIELD_ECN) + vty_out(vty, " ECN Match: %u\n", + pbrms->dsfield & PBR_DSFIELD_ECN); if (pbrms->mark) vty_out(vty, " MARK Match: %u\n", pbrms->mark); @@ -653,6 +744,12 @@ static void vty_json_pbrms(json_object *j, struct vty *vty, prefix2str(pbrms->dst, buf, sizeof(buf))); if (pbrms->mark) json_object_int_add(jpbrm, "matchMark", pbrms->mark); + if (pbrms->dsfield & PBR_DSFIELD_DSCP) + json_object_int_add(jpbrm, "matchDscp", + (pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2); + if (pbrms->dsfield & PBR_DSFIELD_ECN) + json_object_int_add(jpbrm, "matchEcn", + pbrms->dsfield & PBR_DSFIELD_ECN); json_object_array_add(j, jpbrm); } @@ -946,6 +1043,14 @@ static int pbr_vty_map_config_write_sequence(struct vty *vty, vty_out(vty, " match dst-ip %s\n", prefix2str(pbrms->dst, buff, sizeof(buff))); + if (pbrms->dsfield & PBR_DSFIELD_DSCP) + vty_out(vty, " match dscp %u\n", + (pbrms->dsfield & PBR_DSFIELD_DSCP) >> 2); + + if (pbrms->dsfield & PBR_DSFIELD_ECN) + vty_out(vty, " match ecn %u\n", + pbrms->dsfield & PBR_DSFIELD_ECN); + if (pbrms->mark) vty_out(vty, " match mark %u\n", pbrms->mark); @@ -1026,6 +1131,8 @@ void pbr_vty_init(void) install_element(INTERFACE_NODE, &pbr_policy_cmd); install_element(PBRMAP_NODE, &pbr_map_match_src_cmd); install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd); + 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_nexthop_group_cmd); install_element(PBRMAP_NODE, &no_pbr_map_nexthop_group_cmd); |
