summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-03-21 11:59:02 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-04-16 14:40:43 +0200
commit5dd0722dcf41c0baa2834cd23cd64a4dd6100724 (patch)
tree49d6f07ff05f0383bdc7a67c436a49eab88b7c03
parentlib: enhance pbr_rule structure for zapi encode and for common usage (diff)
downloadfrr-5dd0722dcf41c0baa2834cd23cd64a4dd6100724.tar.xz
frr-5dd0722dcf41c0baa2834cd23cd64a4dd6100724.zip
zebra: adapt zebra_pbr_rule based with pbr_rule
In order to avoid duplicates functions, the zebra_pbr_rule structure used by zebra to decode the zapi message, and send netlink messages, is slightly modified. the structure is derived from pbr_rule, but it also includes sock identifier that is used to send back information to the daemon that did the request. Also, the ifp pointer is stored in that structure. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
-rw-r--r--zebra/rule_netlink.c60
-rw-r--r--zebra/zebra_pbr.c38
-rw-r--r--zebra/zebra_pbr.h74
-rw-r--r--zebra/zserv.c59
-rw-r--r--zebra/zserv.h3
5 files changed, 93 insertions, 141 deletions
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index dc942204a..310f0952f 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -66,7 +66,7 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
char buf2[PREFIX_STRLEN];
memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
- family = PREFIX_FAMILY(&rule->filter.src_ip);
+ family = PREFIX_FAMILY(&rule->rule.filter.src_ip);
bytelen = (family == AF_INET ? 4 : 16);
req.n.nlmsg_type = cmd;
@@ -78,7 +78,7 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
req.frh.action = FR_ACT_TO_TBL;
/* rule's pref # */
- addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->priority);
+ addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority);
/* interface on which applied */
if (rule->ifp)
@@ -87,24 +87,24 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
/* source IP, if specified */
if (IS_RULE_FILTERING_ON_SRC_IP(rule)) {
- req.frh.src_len = rule->filter.src_ip.prefixlen;
+ req.frh.src_len = rule->rule.filter.src_ip.prefixlen;
addattr_l(&req.n, sizeof(req), FRA_SRC,
- &rule->filter.src_ip.u.prefix, bytelen);
+ &rule->rule.filter.src_ip.u.prefix, bytelen);
}
/* destination IP, if specified */
if (IS_RULE_FILTERING_ON_DST_IP(rule)) {
- req.frh.dst_len = rule->filter.dst_ip.prefixlen;
+ req.frh.dst_len = rule->rule.filter.dst_ip.prefixlen;
addattr_l(&req.n, sizeof(req), FRA_DST,
- &rule->filter.dst_ip.u.prefix, bytelen);
+ &rule->rule.filter.dst_ip.u.prefix, bytelen);
}
/* Route table to use to forward, if filter criteria matches. */
- if (rule->action.table < 256)
- req.frh.table = rule->action.table;
+ if (rule->rule.action.table < 256)
+ req.frh.table = rule->rule.action.table;
else {
req.frh.table = RT_TABLE_UNSPEC;
addattr32(&req.n, sizeof(req), FRA_TABLE,
- rule->action.table);
+ rule->rule.action.table);
}
if (IS_ZEBRA_DEBUG_KERNEL)
@@ -112,10 +112,12 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
"Tx %s family %s IF %s(%u) Pref %u Src %s Dst %s Table %u",
nl_msg_type_to_str(cmd), nl_family_to_str(family),
rule->ifp ? rule->ifp->name : "Unknown",
- rule->ifp ? rule->ifp->ifindex : 0, rule->priority,
- prefix2str(&rule->filter.src_ip, buf1, sizeof(buf1)),
- prefix2str(&rule->filter.dst_ip, buf2, sizeof(buf2)),
- rule->action.table);
+ rule->ifp ? rule->ifp->ifindex : 0, rule->rule.priority,
+ prefix2str(&rule->rule.filter.src_ip, buf1,
+ sizeof(buf1)),
+ prefix2str(&rule->rule.filter.dst_ip, buf2,
+ sizeof(buf2)),
+ rule->rule.action.table);
/* Ship off the message.
* Note: Currently, netlink_talk() is a blocking call which returns
@@ -210,44 +212,46 @@ int netlink_rule_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
memset(&rule, 0, sizeof(rule));
if (tb[FRA_PRIORITY])
- rule.priority = *(uint32_t *)RTA_DATA(tb[FRA_PRIORITY]);
+ rule.rule.priority = *(uint32_t *)RTA_DATA(tb[FRA_PRIORITY]);
if (tb[FRA_SRC]) {
if (frh->family == AF_INET)
- memcpy(&rule.filter.src_ip.u.prefix4,
+ memcpy(&rule.rule.filter.src_ip.u.prefix4,
RTA_DATA(tb[FRA_SRC]), 4);
else
- memcpy(&rule.filter.src_ip.u.prefix6,
+ memcpy(&rule.rule.filter.src_ip.u.prefix6,
RTA_DATA(tb[FRA_SRC]), 16);
- rule.filter.src_ip.prefixlen = frh->src_len;
- rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
+ rule.rule.filter.src_ip.prefixlen = frh->src_len;
+ rule.rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
}
if (tb[FRA_DST]) {
if (frh->family == AF_INET)
- memcpy(&rule.filter.dst_ip.u.prefix4,
+ memcpy(&rule.rule.filter.dst_ip.u.prefix4,
RTA_DATA(tb[FRA_DST]), 4);
else
- memcpy(&rule.filter.dst_ip.u.prefix6,
+ memcpy(&rule.rule.filter.dst_ip.u.prefix6,
RTA_DATA(tb[FRA_DST]), 16);
- rule.filter.dst_ip.prefixlen = frh->dst_len;
- rule.filter.filter_bm |= PBR_FILTER_DST_IP;
+ rule.rule.filter.dst_ip.prefixlen = frh->dst_len;
+ rule.rule.filter.filter_bm |= PBR_FILTER_DST_IP;
}
if (tb[FRA_TABLE])
- rule.action.table = *(uint32_t *)RTA_DATA(tb[FRA_TABLE]);
+ rule.rule.action.table = *(uint32_t *)RTA_DATA(tb[FRA_TABLE]);
else
- rule.action.table = frh->table;
+ rule.rule.action.table = frh->table;
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"Rx %s family %s IF %s(%u) Pref %u Src %s Dst %s Table %u",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(frh->family), rule.ifp->name,
- rule.ifp->ifindex, rule.priority,
- prefix2str(&rule.filter.src_ip, buf1, sizeof(buf1)),
- prefix2str(&rule.filter.dst_ip, buf2, sizeof(buf2)),
- rule.action.table);
+ rule.ifp->ifindex, rule.rule.priority,
+ prefix2str(&rule.rule.filter.src_ip, buf1,
+ sizeof(buf1)),
+ prefix2str(&rule.rule.filter.dst_ip, buf2,
+ sizeof(buf2)),
+ rule.rule.action.table);
return kernel_pbr_rule_del(&rule);
}
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index eb686bf5a..2d9086c76 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -50,20 +50,22 @@ uint32_t zebra_pbr_rules_hash_key(void *arg)
uint32_t key;
rule = (struct zebra_pbr_rule *)arg;
- key = jhash_3words(rule->seq, rule->priority, rule->action.table,
- prefix_hash_key(&rule->filter.src_ip));
+ key = jhash_3words(rule->rule.seq, rule->rule.priority,
+ rule->rule.action.table,
+ prefix_hash_key(&rule->rule.filter.src_ip));
if (rule->ifp)
key = jhash_1word(rule->ifp->ifindex, key);
else
key = jhash_1word(0, key);
- if (rule->filter.fwmark)
- key = jhash_1word(rule->filter.fwmark, key);
+ if (rule->rule.filter.fwmark)
+ key = jhash_1word(rule->rule.filter.fwmark, key);
else
key = jhash_1word(0, key);
- return jhash_3words(rule->filter.src_port, rule->filter.dst_port,
- prefix_hash_key(&rule->filter.dst_ip),
- jhash_1word(rule->unique, key));
+ return jhash_3words(rule->rule.filter.src_port,
+ rule->rule.filter.dst_port,
+ prefix_hash_key(&rule->rule.filter.dst_ip),
+ jhash_1word(rule->rule.unique, key));
}
int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
@@ -73,31 +75,31 @@ int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
r1 = (const struct zebra_pbr_rule *)arg1;
r2 = (const struct zebra_pbr_rule *)arg2;
- if (r1->seq != r2->seq)
+ if (r1->rule.seq != r2->rule.seq)
return 0;
- if (r1->priority != r2->priority)
+ if (r1->rule.priority != r2->rule.priority)
return 0;
- if (r1->unique != r2->unique)
+ if (r1->rule.unique != r2->rule.unique)
return 0;
- if (r1->action.table != r2->action.table)
+ if (r1->rule.action.table != r2->rule.action.table)
return 0;
- if (r1->filter.src_port != r2->filter.src_port)
+ if (r1->rule.filter.src_port != r2->rule.filter.src_port)
return 0;
- if (r1->filter.dst_port != r2->filter.dst_port)
+ if (r1->rule.filter.dst_port != r2->rule.filter.dst_port)
return 0;
- if (r1->filter.fwmark != r2->filter.fwmark)
+ if (r1->rule.filter.fwmark != r2->rule.filter.fwmark)
return 0;
- if (!prefix_same(&r1->filter.src_ip, &r2->filter.src_ip))
+ if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip))
return 0;
- if (!prefix_same(&r1->filter.dst_ip, &r2->filter.dst_ip))
+ if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip))
return 0;
if (r1->ifp != r2->ifp)
@@ -116,7 +118,7 @@ static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data)
struct pbr_unique_lookup *pul = data;
struct zebra_pbr_rule *rule = b->data;
- if (pul->unique == rule->unique) {
+ if (pul->unique == rule->rule.unique) {
pul->rule = rule;
return HASHWALK_ABORT;
}
@@ -273,7 +275,7 @@ static void *pbr_rule_alloc_intern(void *arg)
void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
{
struct zebra_pbr_rule *unique =
- pbr_rule_lookup_unique(zns, rule->unique);
+ pbr_rule_lookup_unique(zns, rule->rule.unique);
(void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
kernel_add_pbr_rule(rule);
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index 6de33ee2e..0ac629cc6 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -30,80 +30,24 @@
#include "if.h"
#include "rt.h"
+#include "pbr.h"
+struct zebra_pbr_rule {
+ int sock;
-/*
- * A PBR filter
- *
- * The filter or match criteria in a PBR rule.
- * For simplicity, all supported filters are grouped into a structure rather
- * than delineating further. A bitmask denotes which filters are actually
- * specified.
- */
-struct zebra_pbr_filter {
- uint32_t filter_bm;
-#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)
-
- /* Source and Destination IP address with masks. */
- struct prefix src_ip;
- struct prefix dst_ip;
-
- /* Source and Destination higher-layer (TCP/UDP) port numbers. */
- uint16_t src_port;
- uint16_t dst_port;
+ struct pbr_rule rule;
- /* Filter with fwmark */
- uint32_t fwmark;
+ struct interface *ifp;
};
#define IS_RULE_FILTERING_ON_SRC_IP(r) \
- (r->filter.filter_bm & PBR_FILTER_SRC_IP)
+ (r->rule.filter.filter_bm & PBR_FILTER_SRC_IP)
#define IS_RULE_FILTERING_ON_DST_IP(r) \
- (r->filter.filter_bm & PBR_FILTER_DST_IP)
+ (r->rule.filter.filter_bm & PBR_FILTER_DST_IP)
#define IS_RULE_FILTERING_ON_SRC_PORT(r) \
- (r->filter.filter_bm & PBR_FILTER_SRC_PORT)
+ (r->rule.filter.filter_bm & PBR_FILTER_SRC_PORT)
#define IS_RULE_FILTERING_ON_DST_PORT(r) \
- (r->filter.filter_bm & PBR_FILTER_DST_PORT)
-
-/*
- * A PBR action
- *
- * The action corresponding to a PBR rule.
- * While the user specifies the action in a particular way, the forwarding
- * plane implementation (Linux only) requires that to be encoded into a
- * route table and the rule then point to that route table; in some cases,
- * the user criteria may directly point to a table too.
- */
-struct zebra_pbr_action {
- uint32_t table;
-};
-
-/*
- * A PBR rule
- *
- * This is a combination of the filter criteria and corresponding action.
- * Rules also have a user-defined sequence number which defines the relative
- * order amongst rules.
- */
-struct zebra_pbr_rule {
- /*
- * Originating zclient sock fd, so we can know who to send
- * back to.
- */
- int sock;
-
- uint32_t seq;
- uint32_t priority;
- struct interface *ifp;
- uint32_t unique;
- struct zebra_pbr_filter filter;
- struct zebra_pbr_action action;
-};
-
+ (r->rule.filter.filter_bm & PBR_FILTER_DST_PORT)
/*
* An IPSet Entry Filter
diff --git a/zebra/zserv.c b/zebra/zserv.c
index b7bce1f56..94c20c1d1 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -727,7 +727,7 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
- rule->unique);
+ rule->rule.unique);
for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
if (rule->sock == client->sock)
@@ -741,9 +741,9 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
stream_put(s, &note, sizeof(note));
- stream_putl(s, rule->seq);
- stream_putl(s, rule->priority);
- stream_putl(s, rule->unique);
+ stream_putl(s, rule->rule.seq);
+ stream_putl(s, rule->rule.priority);
+ stream_putl(s, rule->rule.unique);
if (rule->ifp)
stream_putl(s, rule->ifp->ifindex);
else
@@ -2757,21 +2757,22 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
memset(&zpr, 0, sizeof(zpr));
zpr.sock = client->sock;
- STREAM_GETL(s, zpr.seq);
- STREAM_GETL(s, zpr.priority);
- STREAM_GETL(s, zpr.unique);
- STREAM_GETC(s, zpr.filter.src_ip.family);
- STREAM_GETC(s, zpr.filter.src_ip.prefixlen);
- STREAM_GET(&zpr.filter.src_ip.u.prefix, s,
- prefix_blen(&zpr.filter.src_ip));
- STREAM_GETW(s, zpr.filter.src_port);
- STREAM_GETC(s, zpr.filter.dst_ip.family);
- STREAM_GETC(s, zpr.filter.dst_ip.prefixlen);
- STREAM_GET(&zpr.filter.dst_ip.u.prefix, s,
- prefix_blen(&zpr.filter.dst_ip));
- STREAM_GETW(s, zpr.filter.dst_port);
- STREAM_GETL(s, zpr.filter.fwmark);
- STREAM_GETL(s, zpr.action.table);
+ zpr.rule.vrf_id = hdr->vrf_id;
+ STREAM_GETL(s, zpr.rule.seq);
+ STREAM_GETL(s, zpr.rule.priority);
+ STREAM_GETL(s, zpr.rule.unique);
+ STREAM_GETC(s, zpr.rule.filter.src_ip.family);
+ STREAM_GETC(s, zpr.rule.filter.src_ip.prefixlen);
+ STREAM_GET(&zpr.rule.filter.src_ip.u.prefix, s,
+ prefix_blen(&zpr.rule.filter.src_ip));
+ STREAM_GETW(s, zpr.rule.filter.src_port);
+ STREAM_GETC(s, zpr.rule.filter.dst_ip.family);
+ STREAM_GETC(s, zpr.rule.filter.dst_ip.prefixlen);
+ STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s,
+ prefix_blen(&zpr.rule.filter.dst_ip));
+ STREAM_GETW(s, zpr.rule.filter.dst_port);
+ STREAM_GETL(s, zpr.rule.filter.fwmark);
+ STREAM_GETL(s, zpr.rule.action.table);
STREAM_GETL(s, ifindex);
if (ifindex) {
@@ -2783,20 +2784,20 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
}
}
- if (!is_default_prefix(&zpr.filter.src_ip))
- zpr.filter.filter_bm |= PBR_FILTER_SRC_IP;
+ if (!is_default_prefix(&zpr.rule.filter.src_ip))
+ zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
- if (!is_default_prefix(&zpr.filter.dst_ip))
- zpr.filter.filter_bm |= PBR_FILTER_DST_IP;
+ if (!is_default_prefix(&zpr.rule.filter.dst_ip))
+ zpr.rule.filter.filter_bm |= PBR_FILTER_DST_IP;
- if (zpr.filter.src_port)
- zpr.filter.filter_bm |= PBR_FILTER_SRC_PORT;
+ if (zpr.rule.filter.src_port)
+ zpr.rule.filter.filter_bm |= PBR_FILTER_SRC_PORT;
- if (zpr.filter.dst_port)
- zpr.filter.filter_bm |= PBR_FILTER_DST_PORT;
+ if (zpr.rule.filter.dst_port)
+ zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT;
- if (zpr.filter.fwmark)
- zpr.filter.filter_bm |= PBR_FILTER_FWMARK;
+ if (zpr.rule.filter.fwmark)
+ zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK;
if (hdr->command == ZEBRA_RULE_ADD)
zebra_pbr_add_rule(zvrf->zns, &zpr);
diff --git a/zebra/zserv.h b/zebra/zserv.h
index f68e87956..503d85f5b 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -28,6 +28,7 @@
#include "routemap.h"
#include "vty.h"
#include "zclient.h"
+#include "pbr.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_pw.h"
@@ -187,10 +188,10 @@ extern int zsend_pw_update(struct zserv *, struct zebra_pw *);
extern int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
enum zapi_route_notify_owner note);
-struct zebra_pbr_rule;
struct zebra_pbr_ipset;
struct zebra_pbr_ipset_entry;
struct zebra_pbr_iptable;
+struct zebra_pbr_rule;
extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
enum zapi_rule_notify_owner note);
extern void zsend_ipset_notify_owner(