diff options
author | Philippe Guibert <philippe.guibert@6wind.com> | 2018-03-21 11:59:02 +0100 |
---|---|---|
committer | Philippe Guibert <philippe.guibert@6wind.com> | 2018-04-16 14:40:43 +0200 |
commit | 5dd0722dcf41c0baa2834cd23cd64a4dd6100724 (patch) | |
tree | 49d6f07ff05f0383bdc7a67c436a49eab88b7c03 | |
parent | lib: enhance pbr_rule structure for zapi encode and for common usage (diff) | |
download | frr-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.c | 60 | ||||
-rw-r--r-- | zebra/zebra_pbr.c | 38 | ||||
-rw-r--r-- | zebra/zebra_pbr.h | 74 | ||||
-rw-r--r-- | zebra/zserv.c | 59 | ||||
-rw-r--r-- | zebra/zserv.h | 3 |
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, ¬e, 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( |