return false;
}
+static void zapi_encode_sockunion(struct stream *s, const union sockunion *su)
+{
+ int family = sockunion_family(su);
+ size_t addrlen = family2addrsize(family);
+
+ /*
+ * Must know length to encode
+ */
+ assert(addrlen);
+
+ stream_putc(s, (uint8_t)family);
+
+ stream_write(s, sockunion_get_addr(su), addrlen);
+}
+
+static bool zapi_decode_sockunion(struct stream *s, union sockunion *su)
+{
+ uint8_t family;
+ size_t addrlen;
+ uint8_t buf[sizeof(union sockunion)];
+
+ memset(su, 0, sizeof(*su));
+
+ STREAM_GETC(s, family);
+ sockunion_family(su) = family;
+
+ addrlen = family2addrsize(family);
+ if (!addrlen)
+ return false;
+
+ if (addrlen > sizeof(buf))
+ return false;
+
+ STREAM_GET(buf, s, addrlen);
+ sockunion_set(su, family, buf, addrlen);
+ return true;
+
+stream_failure:
+ return false;
+}
+
/*
* Encode filter subsection of pbr_rule
*/
if (CHECK_FLAG(a->flags, PBR_ACTION_QUEUE_ID))
stream_putl(s, a->queue_id);
+ /* L3 */
+ if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_IP))
+ zapi_encode_sockunion(s, &a->src_ip);
+ if (CHECK_FLAG(a->flags, PBR_ACTION_DST_IP))
+ zapi_encode_sockunion(s, &a->dst_ip);
+ if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_PORT))
+ stream_putw(s, a->src_port);
+ if (CHECK_FLAG(a->flags, PBR_ACTION_DST_PORT))
+ stream_putw(s, a->dst_port);
+
+ if (CHECK_FLAG(a->flags, PBR_ACTION_DSCP))
+ stream_putc(s, a->dscp & PBR_DSFIELD_DSCP);
+ if (CHECK_FLAG(a->flags, PBR_ACTION_ECN))
+ stream_putc(s, a->ecn & PBR_DSFIELD_ECN);
+
/* L2 */
if (CHECK_FLAG(a->flags, PBR_ACTION_PCP))
stream_putc(s, a->pcp);
if (CHECK_FLAG(a->flags, PBR_ACTION_QUEUE_ID))
STREAM_GETL(s, a->queue_id);
+ /* L3 */
+ if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_IP)) {
+ if (!zapi_decode_sockunion(s, &(a->src_ip)))
+ goto stream_failure;
+ }
+ if (CHECK_FLAG(a->flags, PBR_ACTION_DST_IP))
+ if (!zapi_decode_sockunion(s, &(a->dst_ip)))
+ goto stream_failure;
+
+ if (CHECK_FLAG(a->flags, PBR_ACTION_SRC_PORT))
+ STREAM_GETW(s, a->src_port);
+ if (CHECK_FLAG(a->flags, PBR_ACTION_DST_PORT))
+ STREAM_GETW(s, a->dst_port);
+
+ if (CHECK_FLAG(a->flags, PBR_ACTION_DSCP)) {
+ STREAM_GETC(s, a->dscp);
+ a->dscp &= PBR_DSFIELD_DSCP;
+ }
+ if (CHECK_FLAG(a->flags, PBR_ACTION_ECN)) {
+ STREAM_GETC(s, a->ecn);
+ a->ecn &= PBR_DSFIELD_ECN;
+ }
+
/* L2 */
if (CHECK_FLAG(a->flags, PBR_ACTION_PCP))
STREAM_GETC(s, a->pcp);
uint32_t skip_action_bm, const char **msg)
{
uint32_t filter_bm = pbrms->filter_bm & ~skip_filter_bm;
+ uint32_t action_bm = pbrms->action_bm & ~skip_action_bm;
if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_IP) &&
(family != pbrms->src->family)) {
*msg = "match dst-ip";
return false;
}
+ if (CHECK_FLAG(action_bm, PBR_ACTION_SRC_IP) &&
+ (family != sockunion_family(&pbrms->action_src))) {
+ if (msg)
+ *msg = "set src-ip";
+ return false;
+ }
+ if (CHECK_FLAG(filter_bm, PBR_ACTION_DST_IP) &&
+ (family != sockunion_family(&pbrms->action_dst))) {
+ if (msg)
+ *msg = "set dst-ip";
+ return false;
+ }
return true;
}
"[no] match src-ip ![<A.B.C.D/M|X:X::X:X/M>$prefix]",
NO_STR
"Match the rest of the command\n"
- "Choose the src ip or ipv6 prefix to use\n"
+ "Choose the src ipv4 or ipv6 prefix to use\n"
"v4 Prefix\n"
"v6 Prefix\n")
{
"[no] match dst-ip ![<A.B.C.D/M|X:X::X:X/M>$prefix]",
NO_STR
"Match the rest of the command\n"
- "Choose the dst ip or ipv6 prefix to use\n"
+ "Choose the dst ipv4 or ipv6 prefix to use\n"
"v4 Prefix\n"
"v6 Prefix\n")
{
return CMD_SUCCESS;
}
+/***********************************************************************
+ * pbrms/rule Action Set L3 Fields
+ ***********************************************************************/
+
+/* clang-format off */
+DEFPY (pbr_map_action_src,
+ pbr_map_action_src_cmd,
+ "[no] set src-ip ![<A.B.C.D|X:X::X:X>$su]",
+ NO_STR
+ "Set command\n"
+ "Set the src ipv4 or ipv6 prefix\n"
+ "v4 Prefix\n"
+ "v6 Prefix\n")
+{
+ /* clang-format on */
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ const char *fmsg = NULL;
+
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no) {
+ if (!CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP))
+ return CMD_SUCCESS;
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP);
+ goto check;
+ }
+
+ assert(su);
+ if (!pbr_family_consistent(pbrms, sockunion_family(su),
+ PBR_ACTION_SRC_IP, 0, &fmsg)) {
+ vty_out(vty, "Address family mismatch (%s)\n", fmsg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ pbrms->family = sockunion_family(su);
+
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP) &&
+ (sockunion_same(&pbrms->action_src, su))) {
+ return CMD_SUCCESS;
+ }
+ pbrms->action_src = *su;
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP);
+
+check:
+ pbr_map_check(pbrms, true);
+ return CMD_SUCCESS;
+}
+
+/* clang-format off */
+DEFPY (pbr_map_action_dst,
+ pbr_map_action_dst_cmd,
+ "[no] set dst-ip ![<A.B.C.D|X:X::X:X>$su]",
+ NO_STR
+ "Set command\n"
+ "Set the dst ipv4 or ipv6 prefix\n"
+ "v4 Prefix\n"
+ "v6 Prefix\n")
+{
+ /* clang-format on */
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ const char *fmsg = NULL;
+
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (no) {
+ if (!CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP))
+ return CMD_SUCCESS;
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP);
+ goto check;
+ }
+
+ assert(su);
+ if (!pbr_family_consistent(pbrms, sockunion_family(su),
+ PBR_ACTION_DST_IP, 0, &fmsg)) {
+ vty_out(vty, "Address family mismatch (%s)\n", fmsg);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ pbrms->family = sockunion_family(su);
+
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP) &&
+ (sockunion_same(&pbrms->action_dst, su))) {
+ return CMD_SUCCESS;
+ }
+ pbrms->action_dst = *su;
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP);
+
+check:
+ pbr_map_check(pbrms, true);
+ return CMD_SUCCESS;
+}
+
+/* clang-format off */
+DEFPY (pbr_map_action_src_port,
+ pbr_map_action_src_port_cmd,
+ "[no] set src-port ![(1-65535)$port]",
+ NO_STR
+ "Set command\n"
+ "Set Source Port\n"
+ "The Source Port\n")
+{
+ /* clang-format on */
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (no) {
+ if (!CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT))
+ return CMD_SUCCESS;
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT);
+ goto check;
+ }
+
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT) &&
+ (pbrms->action_src_port == port))
+ return CMD_SUCCESS;
+
+ pbrms->action_src_port = port;
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT);
+
+check:
+ pbr_map_check(pbrms, true);
+ return CMD_SUCCESS;
+}
+
+/* clang-format off */
+DEFPY (pbr_map_action_dst_port,
+ pbr_map_action_dst_port_cmd,
+ "[no] set dst-port ![(1-65535)$port]",
+ NO_STR
+ "Set command\n"
+ "Set Destination Port\n"
+ "The Destination Port\n")
+{
+ /* clang-format on */
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (no) {
+ if (!CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT))
+ return CMD_SUCCESS;
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT);
+ goto check;
+ }
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT) &&
+ (pbrms->action_dst_port == port))
+ return CMD_SUCCESS;
+
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT);
+ pbrms->action_dst_port = port;
+
+check:
+ pbr_map_check(pbrms, true);
+ return CMD_SUCCESS;
+}
+
+/* clang-format off */
+DEFPY (pbr_map_action_dscp,
+ pbr_map_action_dscp_cmd,
+ "[no] set dscp ![DSCP$dscp]",
+ NO_STR
+ "Set command\n"
+ "Set IP DSCP field\n"
+ "DSCP numeric value (0-63) or standard codepoint name\n")
+{
+ /* clang-format on */
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (no) {
+ if (!CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DSCP))
+ return CMD_SUCCESS;
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_DSCP);
+ goto check;
+ }
+
+ unsigned long ul_dscp;
+ char *pend;
+ uint8_t raw_dscp;
+
+ assert(dscp);
+ ul_dscp = strtol(dscp, &pend, 0);
+ if (*pend)
+ raw_dscp = pbr_map_decode_dscp_enum(dscp);
+ else
+ raw_dscp = ul_dscp << 2;
+
+ if (raw_dscp > PBR_DSFIELD_DSCP) {
+ vty_out(vty, "Invalid dscp value: %s%s\n", dscp,
+ (pend ? "" : " (numeric value must be in range 0-63)"));
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DSCP) &&
+ (pbrms->action_dscp == raw_dscp)) {
+ return CMD_SUCCESS;
+ }
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_DSCP);
+ pbrms->action_dscp = raw_dscp;
+
+check:
+ pbr_map_check(pbrms, true);
+ return CMD_SUCCESS;
+}
+
+/* clang-format off */
+DEFPY (pbr_map_action_ecn,
+ pbr_map_action_ecn_cmd,
+ "[no] set ecn ![(0-3)$ecn]",
+ NO_STR
+ "Set command\n"
+ "Set IP ECN field\n"
+ "Explicit Congestion Notification value\n")
+{
+ /* clang-format on */
+ struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+
+ if (no) {
+ if (!CHECK_FLAG(pbrms->action_bm, PBR_ACTION_ECN))
+ return CMD_SUCCESS;
+ UNSET_FLAG(pbrms->action_bm, PBR_ACTION_ECN);
+ goto check;
+ }
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_ECN) &&
+ (pbrms->action_ecn == ecn)) {
+ return CMD_SUCCESS;
+ }
+ SET_FLAG(pbrms->action_bm, PBR_ACTION_ECN);
+ pbrms->action_ecn = ecn;
+
+check:
+ pbr_map_check(pbrms, true);
+ return CMD_SUCCESS;
+}
+
+
/***********************************************************************
* pbrms/rule Action Set Meta
***********************************************************************/
/* set actions */
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP))
+ vty_out(vty, " Set SRC IP: %pSU\n", &pbrms->action_src);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP))
+ vty_out(vty, " Set DST IP: %pSU\n", &pbrms->action_dst);
- if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_QUEUE_ID))
- vty_out(vty, " Set Queue ID: %u\n",
- pbrms->action_queue_id);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT))
+ vty_out(vty, " Set Src port: %u\n",
+ pbrms->action_src_port);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT))
+ vty_out(vty, " Set Dst port: %u\n",
+ pbrms->action_dst_port);
+
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DSCP))
+ vty_out(vty, " Set DSCP: %u\n", (pbrms->action_dscp) >> 2);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_ECN))
+ vty_out(vty, " Set ECN: %u\n", pbrms->action_ecn);
if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_VLAN_ID))
vty_out(vty, " Set VLAN ID %u\n", pbrms->action_vlan_id);
if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_PCP))
vty_out(vty, " Set PCP %u\n", pbrms->action_pcp);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_QUEUE_ID))
+ vty_out(vty, " Set Queue ID: %u\n",
+ pbrms->action_queue_id);
+
switch (pbrms->forwarding_type) {
case PBR_FT_UNSPEC:
* action clauses
*/
+ /* IP header fields */
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP))
+ json_object_string_addf(jpbrm, "actionSetSrcIpAddr", "%pSU",
+ &pbrms->action_src);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP))
+ json_object_string_addf(jpbrm, "actionSetDstIpAddr", "%pSU",
+ &pbrms->action_dst);
+
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT))
+ json_object_int_add(jpbrm, "actionSetSrcPort",
+ pbrms->action_src_port);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT))
+ json_object_int_add(jpbrm, "actionSetDstPort",
+ pbrms->action_dst_port);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DSCP))
+ json_object_int_add(jpbrm, "actionSetDscp",
+ pbrms->action_dscp >> 2);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_ECN))
+ json_object_int_add(jpbrm, "actionSetEcn", pbrms->action_ecn);
/* L2 header fields */
if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_VLAN_STRIP_INNER_ANY))
* action clauses
*/
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_IP))
+ vty_out(vty, " set src-ip %pSU\n", &pbrms->action_src);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_IP))
+ vty_out(vty, " set dst-ip %pSU\n", &pbrms->action_dst);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_SRC_PORT))
+ vty_out(vty, " set src-port %d\n", pbrms->action_src_port);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DST_PORT))
+ vty_out(vty, " set dst-port %d\n", pbrms->action_dst_port);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_DSCP))
+ vty_out(vty, " set dscp %u\n", (pbrms->action_dscp) >> 2);
+ if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_ECN))
+ vty_out(vty, " set ecn %u\n", pbrms->action_ecn);
+
/* L2 header fields */
if (CHECK_FLAG(pbrms->action_bm, PBR_ACTION_VLAN_STRIP_INNER_ANY))
vty_out(vty, " strip vlan any\n");
install_element(PBRMAP_NODE, &pbr_map_match_vlan_tag_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_pcp_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_action_src_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_dst_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_dscp_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_ecn_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_src_port_cmd);
+ install_element(PBRMAP_NODE, &pbr_map_action_dst_port_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);
{"c": "match vlan untagged", "tm": r"VLAN Flags Match: untagged$"},
{"c": "match vlan untagged-or-zero", "tm": r"VLAN Flags Match: untagged-or-zero$"},
{"c": "no match vlan tagged", "tN": r"VLAN Flags Match:"},
-
{"c": "match src-ip 37.49.22.0/24", "tm": r"SRC IP Match: 37.49.22.0/24$"},
{"c": "no match src-ip 37.49.22.0/24", "tN": r"SRC IP Match: 37.49.22.0/24$"},
-
- {"c": "match dst-ip 38.41.29.0/25", "cDN": "foo", "tm": r"DST IP Match: 38.41.29.0/25$"},
+ {
+ "c": "match dst-ip 38.41.29.0/25",
+ "cDN": "foo",
+ "tm": r"DST IP Match: 38.41.29.0/25$",
+ },
{"c": "no match dst-ip 38.41.29.0/25", "tN": r"DST IP Match: 38.41.29.0/25$"},
-
{"c": "match src-port 117", "tm": r"SRC Port Match: 117$"},
{"c": "no match src-port 117", "tN": r"SRC Port Match: 117$"},
-
{"c": "match dst-port 119", "tm": r"DST Port Match: 119$"},
{"c": "no match dst-port 119", "tN": r"DST Port Match: 119$"},
-
{"c": "match dscp cs3", "tm": r"DSCP Match: 24$"},
{"c": "no match dscp cs3", "tN": r"DSCP Match: 24$"},
-
{"c": "match ecn 2", "tm": r"ECN Match: 2$"},
{"c": "no match ecn 2", "tN": r"ECN Match: 2$"},
-
{"c": "match mark 337", "tm": r"MARK Match: 337$"},
{"c": "no match mark 337", "tN": r"MARK Match: 337$"},
+ {"c": "set src-ip 44.100.1.1", "tm": r"Set SRC IP: 44.100.1.1$"},
+ {"c": "no set src-ip 44.100.1.1", "tN": r"Set SRC IP: 44.100.1.1$"},
+ {"c": "set dst-ip 44.105.1.1", "tm": r"Set DST IP: 44.105.1.1$"},
+ {"c": "no set dst-ip 44.105.1.1", "tN": r"Set DST IP: 44.105.1.1$"},
+ {"c": "set src-port 41", "tm": r"Set SRC PORT: 41$"},
+ {"c": "no set src-port 41", "tN": r"Set SRC PORT: 41$"},
+ {"c": "set dst-port 43", "tm": r"Set DST PORT: 43$"},
+ {"c": "no set dst-port 43", "tN": r"Set DST PORT: 43$"},
+ {"c": "set dscp 24", "tm": r"Set DSCP: 24$"},
+ {"c": "no set dscp 24", "tN": r"Set DSCP: 24$"},
+ {"c": "set dscp cs7", "tm": r"Set DSCP: 14$"},
+ {"c": "no set dscp cs7", "tN": r"Set DSCP: 14$"},
+ {"c": "set ecn 1", "tm": r"Set ECN: 1$"},
+ {"c": "no set ecn 1", "tN": r"Set ECN: 1$"},
]