From 0031a6bb2cd94066de1133f2de3a9ce079453631 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 21 Mar 2018 11:55:38 +0100 Subject: [PATCH] lib: enhance pbr_rule structure for zapi encode and for common usage The pbr_rule structure is derived from zebra_pbr_rule, and is defined, so that a zclient will be able to encode the zebra_pbr_rule to send ADD_RULE or DEL_RULE command. Also, the same structure can be used by other daemons to derive a structure ( this will be the case for zebra_pbr_rule). Adding to this, an encoding function is defined, and will be used by remote daemon to encode that message. Those definitions are moved in new file pbr.h file. Signed-off-by: Philippe Guibert --- lib/pbr.h | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/subdir.am | 1 + lib/zclient.c | 50 ++++++++++++++++++++++++++++++ lib/zclient.h | 12 +++---- 4 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 lib/pbr.h diff --git a/lib/pbr.h b/lib/pbr.h new file mode 100644 index 000000000..b49cb562a --- /dev/null +++ b/lib/pbr.h @@ -0,0 +1,86 @@ +/* Policy Based Routing (PBR) main header + * Copyright (C) 2018 6WIND + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _PBR_H +#define _PBR_H + +/* + * 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 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) + + /* 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; + + /* Filter with fwmark */ + uint32_t fwmark; +}; + +/* + * 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 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 pbr_rule { + vrf_id_t vrf_id; + + uint32_t seq; + uint32_t priority; + uint32_t unique; + struct pbr_filter filter; + struct pbr_action action; + uint32_t ifindex; +}; + +extern int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, + struct pbr_rule *zrule); + +#endif /* _PBR_H */ diff --git a/lib/subdir.am b/lib/subdir.am index 7d85b7a24..0319f7764 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -167,6 +167,7 @@ pkginclude_HEADERS += \ lib/zclient.h \ lib/zebra.h \ lib/logicalrouter.h \ + lib/pbr.h \ # end nodist_pkginclude_HEADERS += \ diff --git a/lib/zclient.c b/lib/zclient.c index 34f49c0b4..e1ce40ce7 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -36,6 +36,7 @@ #include "nexthop.h" #include "mpls.h" #include "sockopt.h" +#include "pbr.h" DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient") DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs") @@ -1229,6 +1230,55 @@ stream_failure: return 0; } +static void zapi_encode_prefix(struct stream *s, + struct prefix *p, + uint8_t family) +{ + struct prefix any; + + if (!p) { + memset(&any, 0, sizeof(any)); + any.family = family; + p = &any; + } + + stream_putc(s, p->family); + stream_putc(s, p->prefixlen); + stream_put(s, &p->u.prefix, prefix_blen(p)); +} + +int zapi_pbr_rule_encode(uint8_t cmd, struct stream *s, + struct pbr_rule *zrule) +{ + stream_reset(s); + zclient_create_header(s, cmd, zrule->vrf_id); + + /* + * We are sending one item at a time at the moment + */ + stream_putl(s, 1); + + stream_putl(s, zrule->seq); + stream_putl(s, zrule->priority); + stream_putl(s, zrule->unique); + + zapi_encode_prefix(s, &(zrule->filter.src_ip), + zrule->filter.src_ip.family); + stream_putw(s, zrule->filter.src_port); /* src port */ + zapi_encode_prefix(s, &(zrule->filter.dst_ip), + zrule->filter.src_ip.family); + stream_putw(s, zrule->filter.dst_port); /* dst port */ + stream_putw(s, zrule->filter.fwmark); /* fwmark */ + + stream_putl(s, zrule->action.table); + stream_putl(s, zrule->ifindex); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + return 0; +} + bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, enum zapi_route_notify_owner *note) diff --git a/lib/zclient.h b/lib/zclient.h index 2cdcefd5e..985239b32 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -393,6 +393,12 @@ enum zapi_route_notify_owner { ZAPI_ROUTE_REMOVE_FAIL, }; +enum zapi_rule_notify_owner { + ZAPI_RULE_FAIL_INSTALL, + ZAPI_RULE_INSTALLED, + ZAPI_RULE_REMOVED, +}; + enum ipset_type { IPSET_NET_NET = 1, IPSET_NET_PORT_NET, @@ -400,12 +406,6 @@ enum ipset_type { IPSET_NET }; -enum zapi_rule_notify_owner { - ZAPI_RULE_FAIL_INSTALL, - ZAPI_RULE_INSTALLED, - ZAPI_RULE_REMOVED, -}; - enum zapi_ipset_notify_owner { ZAPI_IPSET_FAIL_INSTALL, ZAPI_IPSET_INSTALLED, -- 2.39.5