diff options
| author | Jafar Al-Gharaibeh <Jafaral@users.noreply.github.com> | 2021-07-27 15:09:29 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-27 15:09:29 -0500 |
| commit | 213d980ff904a30565e1b5fcabafabe49143d35c (patch) | |
| tree | 4cb4bca4547575138df357487c701c3e6e3a37b3 /zebra | |
| parent | 42ac787226bc3b83aa75f6e2040b2808c72b23ec (diff) | |
| parent | 99ed46d964bc8634d5f73e48f2eae5feddac6fd6 (diff) | |
Merge pull request #9007 from donaldsharp/pbr_stuff
add ability to match on proto to pbr
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/kernel_netlink.c | 6 | ||||
| -rw-r--r-- | zebra/kernel_netlink.h | 2 | ||||
| -rw-r--r-- | zebra/rule_netlink.c | 34 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 16 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_pbr.c | 9 |
7 files changed, 57 insertions, 16 deletions
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 8b631a3726..011883649d 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -550,6 +550,12 @@ bool nl_attr_put(struct nlmsghdr *n, unsigned int maxlen, int type, return true; } +bool nl_attr_put8(struct nlmsghdr *n, unsigned int maxlen, int type, + uint8_t data) +{ + return nl_attr_put(n, maxlen, type, &data, sizeof(uint8_t)); +} + bool nl_attr_put16(struct nlmsghdr *n, unsigned int maxlen, int type, uint16_t data) { diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index a7b152b31b..d8e5671b72 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -38,6 +38,8 @@ extern "C" { */ extern bool nl_attr_put(struct nlmsghdr *n, unsigned int maxlen, int type, const void *data, unsigned int alen); +extern bool nl_attr_put8(struct nlmsghdr *n, unsigned int maxlen, int type, + uint8_t data); extern bool nl_attr_put16(struct nlmsghdr *n, unsigned int maxlen, int type, uint16_t data); extern bool nl_attr_put32(struct nlmsghdr *n, unsigned int maxlen, int type, diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index 08a675ef3a..b651edd8f9 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -58,12 +58,11 @@ * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer * or the number of bytes written to buf. */ -static ssize_t -netlink_rule_msg_encode(int cmd, const struct zebra_dplane_ctx *ctx, - uint32_t filter_bm, uint32_t priority, uint32_t table, - const struct prefix *src_ip, - const struct prefix *dst_ip, uint32_t fwmark, - uint8_t dsfield, void *buf, size_t buflen) +static ssize_t netlink_rule_msg_encode( + int cmd, const struct zebra_dplane_ctx *ctx, uint32_t filter_bm, + uint32_t priority, uint32_t table, const struct prefix *src_ip, + const struct prefix *dst_ip, uint32_t fwmark, uint8_t dsfield, + uint8_t ip_protocol, void *buf, size_t buflen) { uint8_t protocol = RTPROT_ZEBRA; int family; @@ -136,6 +135,10 @@ netlink_rule_msg_encode(int cmd, const struct zebra_dplane_ctx *ctx, if (filter_bm & PBR_FILTER_DSFIELD) req->frh.tos = dsfield; + /* protocol to match on */ + if (filter_bm & PBR_FILTER_IP_PROTOCOL) + nl_attr_put8(&req->n, buflen, FRA_IP_PROTO, ip_protocol); + /* Route table to use to forward, if filter criteria matches. */ if (table < 256) req->frh.table = table; @@ -168,7 +171,8 @@ static ssize_t netlink_rule_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf, dplane_ctx_rule_get_table(ctx), dplane_ctx_rule_get_src_ip(ctx), dplane_ctx_rule_get_dst_ip(ctx), dplane_ctx_rule_get_fwmark(ctx), - dplane_ctx_rule_get_dsfield(ctx), buf, buflen); + dplane_ctx_rule_get_dsfield(ctx), + dplane_ctx_rule_get_ipproto(ctx), buf, buflen); } static ssize_t netlink_oldrule_msg_encoder(struct zebra_dplane_ctx *ctx, @@ -181,7 +185,8 @@ static ssize_t netlink_oldrule_msg_encoder(struct zebra_dplane_ctx *ctx, dplane_ctx_rule_get_old_src_ip(ctx), dplane_ctx_rule_get_old_dst_ip(ctx), dplane_ctx_rule_get_old_fwmark(ctx), - dplane_ctx_rule_get_old_dsfield(ctx), buf, buflen); + dplane_ctx_rule_get_old_dsfield(ctx), + dplane_ctx_rule_get_old_ipproto(ctx), buf, buflen); } /* Public functions */ @@ -236,6 +241,7 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) char *ifname; struct zebra_pbr_rule rule = {}; uint8_t proto = 0; + uint8_t ip_proto = 0; /* Basic validation followed by extracting attributes. */ if (h->nlmsg_type != RTM_NEWRULE && h->nlmsg_type != RTM_DELRULE) @@ -312,6 +318,9 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (tb[FRA_PROTOCOL]) proto = *(uint8_t *)RTA_DATA(tb[FRA_PROTOCOL]); + if (tb[FRA_IP_PROTO]) + ip_proto = *(uint8_t *)RTA_DATA(tb[FRA_IP_PROTO]); + ifname = (char *)RTA_DATA(tb[FRA_IFNAME]); strlcpy(rule.ifname, ifname, sizeof(rule.ifname)); @@ -326,7 +335,7 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) ret = dplane_pbr_rule_delete(&rule); zlog_debug( - "%s: %s leftover rule: family %s IF %s Pref %u Src %pFX Dst %pFX Table %u", + "%s: %s leftover rule: family %s IF %s Pref %u Src %pFX Dst %pFX Table %u ip-proto: %u", __func__, ((ret == ZEBRA_DPLANE_REQUEST_FAILURE) ? "Failed to remove" @@ -334,7 +343,7 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) nl_family_to_str(frh->family), rule.ifname, rule.rule.priority, &rule.rule.filter.src_ip, &rule.rule.filter.dst_ip, - rule.rule.action.table); + rule.rule.action.table, ip_proto); } /* TBD */ @@ -349,11 +358,12 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "Rx %s family %s IF %s Pref %u Src %pFX Dst %pFX Table %u", + "Rx %s family %s IF %s Pref %u Src %pFX Dst %pFX Table %u ip-proto: %u", nl_msg_type_to_str(h->nlmsg_type), nl_family_to_str(frh->family), rule.ifname, rule.rule.priority, &rule.rule.filter.src_ip, - &rule.rule.filter.dst_ip, rule.rule.action.table); + &rule.rule.filter.dst_ip, rule.rule.action.table, + ip_proto); return kernel_pbr_rule_del(&rule); } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 5b2b1cc26f..27fb5d7c22 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3131,6 +3131,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) STREAM_GETL(s, zpr.rule.seq); STREAM_GETL(s, zpr.rule.priority); STREAM_GETL(s, zpr.rule.unique); + STREAM_GETC(s, zpr.rule.filter.ip_proto); 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, @@ -3164,6 +3165,9 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) if (zpr.rule.filter.dsfield) zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD; + if (zpr.rule.filter.ip_proto) + zpr.rule.filter.filter_bm |= PBR_FILTER_IP_PROTOCOL; + if (zpr.rule.filter.fwmark) zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 1217ed915a..2a30fc6eef 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -259,6 +259,7 @@ struct dplane_ctx_rule { uint8_t dsfield; struct prefix src_ip; struct prefix dst_ip; + uint8_t ip_proto; char ifname[INTERFACE_NAMSIZ + 1]; }; @@ -1929,6 +1930,20 @@ uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx) return ctx->u.rule.old.fwmark; } +uint8_t dplane_ctx_rule_get_ipproto(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.rule.new.ip_proto; +} + +uint8_t dplane_ctx_rule_get_old_ipproto(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.rule.old.ip_proto; +} + uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -2636,6 +2651,7 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule, dplane_rule->filter_bm = rule->rule.filter.filter_bm; dplane_rule->fwmark = rule->rule.filter.fwmark; dplane_rule->dsfield = rule->rule.filter.dsfield; + dplane_rule->ip_proto = rule->rule.filter.ip_proto; prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip); prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip); strlcpy(dplane_rule->ifname, rule->ifname, INTERFACE_NAMSIZ); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index e091655a48..5ec1bd5807 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -493,6 +493,8 @@ uint32_t dplane_ctx_rule_get_fwmark(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx); uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx); uint8_t dplane_ctx_rule_get_old_dsfield(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_rule_get_ipproto(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_rule_get_old_ipproto(const struct zebra_dplane_ctx *ctx); const struct prefix * dplane_ctx_rule_get_src_ip(const struct zebra_dplane_ctx *ctx); const struct prefix * diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 7bcd097371..3607110aa2 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -166,10 +166,8 @@ uint32_t zebra_pbr_rules_hash_key(const void *arg) rule->rule.action.table, prefix_hash_key(&rule->rule.filter.src_ip)); - if (rule->rule.filter.fwmark) - key = jhash_2words(rule->rule.filter.fwmark, rule->vrf_id, key); - else - key = jhash_1word(rule->vrf_id, key); + key = jhash_3words(rule->rule.filter.fwmark, rule->vrf_id, + rule->rule.filter.ip_proto, key); key = jhash(rule->ifname, strlen(rule->ifname), key); @@ -207,6 +205,9 @@ bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) if (r1->rule.filter.fwmark != r2->rule.filter.fwmark) return false; + if (r1->rule.filter.ip_proto != r2->rule.filter.ip_proto) + return false; + if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip)) return false; |
