diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/kernel_netlink.c | 6 | ||||
| -rw-r--r-- | zebra/kernel_netlink.h | 2 | ||||
| -rw-r--r-- | zebra/redistribute.c | 6 | ||||
| -rw-r--r-- | zebra/rule_netlink.c | 34 | ||||
| -rw-r--r-- | zebra/zapi_msg.c | 6 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 16 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_mpls.c | 34 | ||||
| -rw-r--r-- | zebra/zebra_mpls.h | 6 | ||||
| -rw-r--r-- | zebra/zebra_pbr.c | 9 | ||||
| -rw-r--r-- | zebra/zebra_vrf.h | 1 | ||||
| -rw-r--r-- | zebra/zserv.c | 2 |
12 files changed, 108 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/redistribute.c b/zebra/redistribute.c index 89f46f9c97..26f6d404e9 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -153,10 +153,16 @@ static bool zebra_redistribute_check(const struct route_entry *re, struct zserv *client, const struct prefix *p, int afi) { + struct zebra_vrf *zvrf; + /* Process only if there is valid re */ if (!re) return false; + zvrf = vrf_info_lookup(re->vrf_id); + if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) + return false; + /* If default route and redistributed */ if (is_default_prefix(p) && vrf_bitmap_check(client->redist_default[afi], re->vrf_id)) 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 a53e388062..27fb5d7c22 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3107,6 +3107,8 @@ static void zread_vrf_label(ZAPI_HANDLER_ARGS) } zvrf->label[afi] = nlabel; + zvrf->label_proto[afi] = client->proto; + stream_failure: return; } @@ -3129,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, @@ -3162,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_mpls.c b/zebra/zebra_mpls.c index a2d1513ce4..66d2d6b4ba 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -3932,6 +3932,40 @@ void zebra_mpls_cleanup_tables(struct zebra_vrf *zvrf) } /* + * When a vrf label is assigned and the client goes away + * we should cleanup the vrf labels associated with + * that zclient. + */ +void zebra_mpls_client_cleanup_vrf_label(uint8_t proto) +{ + struct vrf *vrf; + struct zebra_vrf *def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + + if (def_zvrf == NULL) + return; + + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + struct zebra_vrf *zvrf = vrf->info; + afi_t afi; + + if (!zvrf) + continue; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + if (zvrf->label_proto[afi] == proto + && zvrf->label[afi] != MPLS_LABEL_NONE) + lsp_uninstall(def_zvrf, zvrf->label[afi]); + + /* + * Cleanup data structures by fiat + */ + zvrf->label_proto[afi] = 0; + zvrf->label[afi] = MPLS_LABEL_NONE; + } + } +} + +/* * Called upon process exiting, need to delete LSP forwarding * entries from the kernel. * NOTE: Currently supported only for default VRF. diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 7059d393ed..5195b2f14f 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -416,6 +416,12 @@ void zebra_mpls_init(void); */ void zebra_mpls_vty_init(void); +/* + * When cleaning up a client connection ensure that there are no + * vrf labels that need cleaning up too + */ +void zebra_mpls_client_cleanup_vrf_label(uint8_t proto); + /* Inline functions. */ /* 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; diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 57dd0c20ad..f32f09850b 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -105,6 +105,7 @@ struct zebra_vrf { /* MPLS Label to handle L3VPN <-> vrf popping */ mpls_label_t label[AFI_MAX]; + uint8_t label_proto[AFI_MAX]; /* MPLS static LSP config table */ struct hash *slsp_table; diff --git a/zebra/zserv.c b/zebra/zserv.c index 1d94fcae6b..e4a48093f7 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -595,6 +595,8 @@ static void zserv_client_free(struct zserv *client) close(client->sock); if (DYNAMIC_CLIENT_GR_DISABLED(client)) { + zebra_mpls_client_cleanup_vrf_label(client->proto); + nroutes = rib_score_proto(client->proto, client->instance); zlog_notice( |
