summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/nexthop_group.c1
-rw-r--r--lib/pbr.h37
-rw-r--r--lib/zclient.c197
3 files changed, 193 insertions, 42 deletions
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 0613fc6736..25370eba48 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -1047,6 +1047,7 @@ void nexthop_group_write_nexthop_simple(struct vty *vty,
vty_out(vty, "%pI6 %s", &nh->gate.ipv6, ifname);
break;
case NEXTHOP_TYPE_BLACKHOLE:
+ vty_out(vty, "%s", "drop");
break;
}
}
diff --git a/lib/pbr.h b/lib/pbr.h
index 1a3d562ed9..c514cc2a65 100644
--- a/lib/pbr.h
+++ b/lib/pbr.h
@@ -34,17 +34,18 @@ struct pbr_filter {
#define PBR_FILTER_SRC_PORT (1 << 2)
#define PBR_FILTER_DST_PORT (1 << 3)
#define PBR_FILTER_FWMARK (1 << 4)
-#define PBR_FILTER_PROTO (1 << 5)
+#define PBR_FILTER_IP_PROTOCOL (1 << 5)
#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_DSCP (1 << 8)
+#define PBR_FILTER_ECN (1 << 9)
#define PBR_FILTER_PCP (1 << 10)
#define PBR_FILTER_VLAN_FLAGS (1 << 11)
#define PBR_FILTER_VLAN_ID (1 << 12)
#define PBR_DSFIELD_DSCP (0xfc) /* Upper 6 bits of DS field: DSCP */
#define PBR_DSFIELD_ECN (0x03) /* Lower 2 bits of DS field: BCN */
+
#define PBR_PCP (0x07) /* 3-bit value 0..7 for prioritization*/
#define PBR_VLAN_FLAGS_NO_WILD 0
@@ -56,7 +57,7 @@ struct pbr_filter {
struct prefix src_ip;
struct prefix dst_ip;
- /* Source and Destination higher-layer (TCP/UDP) port numbers */
+ /* Source and Destination layer 4 (TCP/UDP/etc.) port numbers */
uint16_t src_port;
uint16_t dst_port;
@@ -87,11 +88,17 @@ struct pbr_filter {
struct pbr_action {
uint32_t flags;
-#define PBR_ACTION_TABLE (1 << 0)
-#define PBR_ACTION_QUEUE_ID (1 << 1)
-#define PBR_ACTION_PCP (1 << 2)
-#define PBR_ACTION_VLAN_ID (1 << 3)
-#define PBR_ACTION_VLAN_FLAGS (1 << 4)
+#define PBR_ACTION_TABLE (1 << 0)
+#define PBR_ACTION_QUEUE_ID (1 << 1)
+#define PBR_ACTION_PCP (1 << 2)
+#define PBR_ACTION_VLAN_ID (1 << 3)
+#define PBR_ACTION_VLAN_STRIP_INNER_ANY (1 << 4)
+#define PBR_ACTION_SRC_IP (1 << 5)
+#define PBR_ACTION_DST_IP (1 << 6)
+#define PBR_ACTION_SRC_PORT (1 << 7)
+#define PBR_ACTION_DST_PORT (1 << 8)
+#define PBR_ACTION_DSCP (1 << 9)
+#define PBR_ACTION_ECN (1 << 10)
uint32_t table;
uint32_t queue_id;
@@ -99,9 +106,18 @@ struct pbr_action {
/* VLAN */
uint8_t pcp;
uint16_t vlan_id;
- uint16_t vlan_flags;
+ /* Source and Destination IP addresses */
+ union sockunion src_ip;
+ union sockunion dst_ip;
+
+ /* Source and Destination layer 4 (TCP/UDP/etc.) port numbers */
+ uint32_t src_port;
+ uint32_t dst_port;
+ /* Differentiated Services field */
+ uint8_t dscp; /* stored here already shifted to upper 6 bits */
+ uint8_t ecn; /* stored here as lower 2 bits */
};
/*
@@ -113,6 +129,7 @@ struct pbr_action {
*/
struct pbr_rule {
vrf_id_t vrf_id;
+ uint8_t family; /* netlink: select which rule database */
uint32_t seq;
uint32_t priority;
diff --git a/lib/zclient.c b/lib/zclient.c
index 294a78feb0..e40725826a 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1622,6 +1622,47 @@ stream_failure:
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
*/
@@ -1631,40 +1672,79 @@ static void zapi_pbr_rule_filter_encode(struct stream *s, struct pbr_filter *f)
assert((f->src_ip.family == AF_INET) || (f->src_ip.family == AF_INET6));
stream_putl(s, f->filter_bm);
- stream_putc(s, f->ip_proto);
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_IP_PROTOCOL))
+ stream_putc(s, f->ip_proto);
/* addresses */
- zapi_encode_prefix(s, &f->src_ip, f->src_ip.family);
- zapi_encode_prefix(s, &f->dst_ip, f->dst_ip.family);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_IP))
+ zapi_encode_prefix(s, &f->src_ip, f->src_ip.family);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_IP))
+ zapi_encode_prefix(s, &f->dst_ip, f->dst_ip.family);
/* port numbers */
- stream_putw(s, f->src_port);
- stream_putw(s, f->dst_port);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_PORT))
+ stream_putw(s, f->src_port);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_PORT))
+ stream_putw(s, f->dst_port);
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DSCP))
+ stream_putc(s, f->dsfield & PBR_DSFIELD_DSCP);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_ECN))
+ stream_putc(s, f->dsfield & PBR_DSFIELD_ECN);
/* vlan */
- stream_putc(s, f->pcp);
- stream_putw(s, f->vlan_id);
- stream_putw(s, f->vlan_flags);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_PCP))
+ stream_putc(s, f->pcp);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_ID))
+ stream_putw(s, f->vlan_id);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_FLAGS))
+ stream_putw(s, f->vlan_flags);
+
- stream_putc(s, f->dsfield);
- stream_putl(s, f->fwmark);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_FWMARK))
+ stream_putl(s, f->fwmark);
}
static bool zapi_pbr_rule_filter_decode(struct stream *s, struct pbr_filter *f)
{
+ uint8_t dscp = 0;
+ uint8_t ecn = 0;
+
STREAM_GETL(s, f->filter_bm);
- STREAM_GETC(s, f->ip_proto);
- if (!zapi_decode_prefix(s, &(f->src_ip)))
- goto stream_failure;
- if (!zapi_decode_prefix(s, &(f->dst_ip)))
- goto stream_failure;
- STREAM_GETW(s, f->src_port);
- STREAM_GETW(s, f->dst_port);
- STREAM_GETC(s, f->pcp);
- STREAM_GETW(s, f->vlan_id);
- STREAM_GETW(s, f->vlan_flags);
- STREAM_GETC(s, f->dsfield);
- STREAM_GETL(s, f->fwmark);
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_IP_PROTOCOL))
+ STREAM_GETC(s, f->ip_proto);
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_IP))
+ if (!zapi_decode_prefix(s, &(f->src_ip)))
+ goto stream_failure;
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_IP))
+ if (!zapi_decode_prefix(s, &(f->dst_ip)))
+ goto stream_failure;
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_SRC_PORT))
+ STREAM_GETW(s, f->src_port);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DST_PORT))
+ STREAM_GETW(s, f->dst_port);
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_DSCP))
+ STREAM_GETC(s, dscp);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_ECN))
+ STREAM_GETC(s, ecn);
+ f->dsfield = (dscp & PBR_DSFIELD_DSCP) | (ecn & PBR_DSFIELD_ECN);
+
+ /* vlan */
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_PCP))
+ STREAM_GETC(s, f->pcp);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_ID))
+ STREAM_GETW(s, f->vlan_id);
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_VLAN_FLAGS))
+ STREAM_GETW(s, f->vlan_flags);
+
+ if (CHECK_FLAG(f->filter_bm, PBR_FILTER_FWMARK))
+ STREAM_GETL(s, f->fwmark);
+
return true;
stream_failure:
@@ -1674,21 +1754,72 @@ stream_failure:
static void zapi_pbr_rule_action_encode(struct stream *s, struct pbr_action *a)
{
stream_putl(s, a->flags);
- stream_putl(s, a->table);
- stream_putl(s, a->queue_id);
- stream_putc(s, a->pcp);
- stream_putw(s, a->vlan_id);
- stream_putw(s, a->vlan_flags);
+
+ if (CHECK_FLAG(a->flags, PBR_ACTION_TABLE))
+ stream_putl(s, a->table);
+ 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_VLAN_ID))
+ stream_putw(s, a->vlan_id);
}
static bool zapi_pbr_rule_action_decode(struct stream *s, struct pbr_action *a)
{
STREAM_GETL(s, a->flags);
- STREAM_GETL(s, a->table);
- STREAM_GETL(s, a->queue_id);
- STREAM_GETC(s, a->pcp);
- STREAM_GETW(s, a->vlan_id);
- STREAM_GETW(s, a->vlan_flags);
+
+ if (CHECK_FLAG(a->flags, PBR_ACTION_TABLE))
+ STREAM_GETL(s, a->table);
+ 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);
+ if (CHECK_FLAG(a->flags, PBR_ACTION_VLAN_ID))
+ STREAM_GETW(s, a->vlan_id);
+
return true;
stream_failure:
@@ -1702,6 +1833,7 @@ int zapi_pbr_rule_encode(struct stream *s, struct pbr_rule *r)
*/
stream_putl(s, 1);
+ stream_putc(s, r->family);
stream_putl(s, r->seq);
stream_putl(s, r->priority);
stream_putl(s, r->unique);
@@ -1723,6 +1855,7 @@ bool zapi_pbr_rule_decode(struct stream *s, struct pbr_rule *r)
memset(r, 0, sizeof(*r));
+ STREAM_GETC(s, r->family);
STREAM_GETL(s, r->seq);
STREAM_GETL(s, r->priority);
STREAM_GETL(s, r->unique);