zebra: add 3 fields to ipset_entry : src,dst port, and proto

Those 3 fields are read and written between zebra and bgpd.
This permits extending the ipset_entry structure.
Combinatories will be possible:
- filtering with one of the src/dst port.
- filtering with one of the range src/ range dst port
usage of src or dst is exclusive in a FS entry.
- filtering a port or a port range based on either src or dst port.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2018-03-30 13:01:39 +02:00
parent 586f4ccf2c
commit 25d760c551
4 changed files with 94 additions and 7 deletions

View File

@ -31,11 +31,14 @@
struct pbr_filter {
uint32_t filter_bm; /* not encoded by zapi
*/
#define PBR_FILTER_SRC_IP (1 << 0)
#define PBR_FILTER_DST_IP (1 << 1)
#define PBR_FILTER_SRC_PORT (1 << 2)
#define PBR_FILTER_DST_PORT (1 << 3)
#define PBR_FILTER_FWMARK (1 << 4)
#define PBR_FILTER_SRC_IP (1 << 0)
#define PBR_FILTER_DST_IP (1 << 1)
#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_SRC_PORT_RANGE (1 << 6)
#define PBR_FILTER_DST_PORT_RANGE (1 << 7)
/* Source and Destination IP address with masks. */
struct prefix src_ip;

View File

@ -2886,11 +2886,26 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
STREAM_GETC(s, zpi.dst.prefixlen);
STREAM_GET(&zpi.dst.u.prefix, s, prefix_blen(&zpi.dst));
STREAM_GETW(s, zpi.src_port_min);
STREAM_GETW(s, zpi.src_port_max);
STREAM_GETW(s, zpi.dst_port_min);
STREAM_GETW(s, zpi.dst_port_max);
STREAM_GETC(s, zpi.proto);
if (!is_default_prefix(&zpi.src))
zpi.filter_bm |= PBR_FILTER_SRC_IP;
if (!is_default_prefix(&zpi.dst))
zpi.filter_bm |= PBR_FILTER_DST_IP;
if (zpi.dst_port_min != 0)
zpi.filter_bm |= PBR_FILTER_DST_PORT;
if (zpi.src_port_min != 0)
zpi.filter_bm |= PBR_FILTER_SRC_PORT;
if (zpi.dst_port_max != 0)
zpi.filter_bm |= PBR_FILTER_DST_PORT_RANGE;
if (zpi.src_port_max != 0)
zpi.filter_bm |= PBR_FILTER_SRC_PORT_RANGE;
if (zpi.proto != 0)
zpi.filter_bm |= PBR_FILTER_PROTO;
/* calculate backpointer */
zpi.backpointer = zebra_pbr_lookup_ipset_pername(

View File

@ -201,6 +201,11 @@ uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
key = prefix_hash_key(&ipset->src);
key = jhash_1word(ipset->unique, key);
key = jhash_1word(prefix_hash_key(&ipset->dst), key);
key = jhash(&ipset->dst_port_min, 2, key);
key = jhash(&ipset->dst_port_max, 2, key);
key = jhash(&ipset->src_port_min, 2, key);
key = jhash(&ipset->src_port_max, 2, key);
key = jhash(&ipset->proto, 1, key);
return key;
}
@ -221,6 +226,20 @@ int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
if (!prefix_same(&r1->dst, &r2->dst))
return 0;
if (r1->src_port_min != r2->src_port_min)
return 0;
if (r1->src_port_max != r2->src_port_max)
return 0;
if (r1->dst_port_min != r2->dst_port_min)
return 0;
if (r1->dst_port_max != r2->dst_port_max)
return 0;
if (r1->proto != r2->proto)
return 0;
return 1;
}
@ -670,6 +689,27 @@ static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
return prefix2str(pu, str, size);
}
static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
uint16_t port_min, uint16_t port_max,
uint8_t proto)
{
if (!(filter_bm & PBR_FILTER_PROTO)) {
if (port_max)
vty_out(vty, ":udp/tcp:%d-%d",
port_min, port_max);
else
vty_out(vty, ":udp/tcp:%d",
port_min);
} else {
if (port_max)
vty_out(vty, ":proto %d:%d-%d",
proto, port_min, port_max);
else
vty_out(vty, ":proto %d:%d",
proto, port_min);
}
}
static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
void *arg)
{
@ -683,25 +723,47 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
if (zpie->backpointer != zpi)
return HASHWALK_CONTINUE;
if (zpi->type == IPSET_NET_NET) {
if ((zpi->type == IPSET_NET_NET) ||
(zpi->type == IPSET_NET_PORT_NET)) {
char buf[PREFIX_STRLEN];
zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
vty_out(vty, "\tfrom %s", buf);
if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->src_port_min,
zpie->src_port_max,
zpie->proto);
vty_out(vty, " to ");
zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
vty_out(vty, "%s", buf);
} else if (zpi->type == IPSET_NET) {
if (zpie->filter_bm & PBR_FILTER_DST_PORT)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->dst_port_min,
zpie->dst_port_max,
zpie->proto);
} else if ((zpi->type == IPSET_NET) ||
(zpi->type == IPSET_NET_PORT)) {
char buf[PREFIX_STRLEN];
if (zpie->filter_bm & PBR_FILTER_SRC_IP) {
zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
vty_out(vty, "\tfrom %s", buf);
}
if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->src_port_min,
zpie->src_port_max,
zpie->proto);
if (zpie->filter_bm & PBR_FILTER_DST_IP) {
zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
vty_out(vty, "\tto %s", buf);
}
if (zpie->filter_bm & PBR_FILTER_DST_PORT)
zebra_pbr_display_port(vty, zpie->filter_bm,
zpie->dst_port_min,
zpie->dst_port_max,
zpie->proto);
}
vty_out(vty, " (%u)\n", zpie->unique);

View File

@ -91,6 +91,13 @@ struct zebra_pbr_ipset_entry {
struct prefix src;
struct prefix dst;
uint16_t src_port_min;
uint16_t src_port_max;
uint16_t dst_port_min;
uint16_t dst_port_max;
uint8_t proto;
uint32_t filter_bm;
struct zebra_pbr_ipset *backpointer;