diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index c64d9f6ab2..2122f9f5fa 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -51,8 +51,7 @@ * Form netlink message and ship it. Currently, notify status after * waiting for netlink status. */ -static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule, - struct interface *ifp) +static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule) { int family; int bytelen; @@ -85,9 +84,9 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule, addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->priority); /* interface on which applied */ - if (ifp) - addattr_l(&req.n, sizeof(req), FRA_IFNAME, ifp->name, - strlen(ifp->name) + 1); + if (rule->ifp) + addattr_l(&req.n, sizeof(req), FRA_IFNAME, rule->ifp->name, + strlen(rule->ifp->name) + 1); /* source IP, if specified */ if (IS_RULE_FILTERING_ON_SRC_IP(rule)) { @@ -115,8 +114,8 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule, zlog_debug( "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), - ifp ? ifp->name : "Unknown", ifp ? ifp->ifindex : 0, - rule->priority, + 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); @@ -138,12 +137,12 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule, * goes in the rule to denote relative ordering; it may or may not be the * same as the rule's user-defined sequence number. */ -void kernel_add_pbr_rule(struct zebra_pbr_rule *rule, struct interface *ifp) +void kernel_add_pbr_rule(struct zebra_pbr_rule *rule) { int ret = 0; - ret = netlink_rule_update(RTM_NEWRULE, rule, ifp); - kernel_pbr_rule_add_del_status(rule, ifp, + ret = netlink_rule_update(RTM_NEWRULE, rule); + kernel_pbr_rule_add_del_status(rule, (!ret) ? SOUTHBOUND_INSTALL_SUCCESS : SOUTHBOUND_INSTALL_FAILURE); } @@ -151,12 +150,12 @@ void kernel_add_pbr_rule(struct zebra_pbr_rule *rule, struct interface *ifp) /* * Uninstall specified rule for a specific interface. */ -void kernel_del_pbr_rule(struct zebra_pbr_rule *rule, struct interface *ifp) +void kernel_del_pbr_rule(struct zebra_pbr_rule *rule) { int ret = 0; - ret = netlink_rule_update(RTM_DELRULE, rule, ifp); - kernel_pbr_rule_add_del_status(rule, ifp, + ret = netlink_rule_update(RTM_DELRULE, rule); + kernel_pbr_rule_add_del_status(rule, (!ret) ? SOUTHBOUND_DELETE_SUCCESS : SOUTHBOUND_DELETE_FAILURE); } @@ -176,7 +175,6 @@ int netlink_rule_change(struct sockaddr_nl *snl, struct nlmsghdr *h, struct rtattr *tb[FRA_MAX + 1]; int len; char *ifname; - struct interface *ifp; struct zebra_pbr_rule rule; char buf1[PREFIX_STRLEN]; char buf2[PREFIX_STRLEN]; @@ -209,8 +207,8 @@ int netlink_rule_change(struct sockaddr_nl *snl, struct nlmsghdr *h, /* If we don't know the interface, we don't care. */ ifname = (char *)RTA_DATA(tb[FRA_IFNAME]); zns = zebra_ns_lookup(ns_id); - ifp = if_lookup_by_name_per_ns(zns, ifname); - if (!ifp) + rule.ifp = if_lookup_by_name_per_ns(zns, ifname); + if (!rule.ifp) return 0; memset(&rule, 0, sizeof(rule)); @@ -248,13 +246,13 @@ int netlink_rule_change(struct sockaddr_nl *snl, struct nlmsghdr *h, 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), ifp->name, ifp->ifindex, - rule.priority, + 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); - return kernel_pbr_rule_del(&rule, ifp); + return kernel_pbr_rule_del(&rule); } /* diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 3f8655552b..0096da942e 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -40,7 +40,7 @@ void zebra_pbr_rules_free(void *arg) rule = (struct zebra_pbr_rule *)arg; - kernel_del_pbr_rule(rule, NULL); + kernel_del_pbr_rule(rule); XFREE(MTYPE_TMP, rule); } @@ -52,6 +52,11 @@ uint32_t zebra_pbr_rules_hash_key(void *arg) rule = (struct zebra_pbr_rule *)arg; key = jhash_3words(rule->seq, rule->priority, rule->action.table, prefix_hash_key(&rule->filter.src_ip)); + if (rule->ifp) + key = jhash_1word(rule->ifp->ifindex, 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), key); } @@ -84,6 +89,9 @@ int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) if (!prefix_same(&r1->filter.dst_ip, &r2->filter.dst_ip)) return 0; + if (r1->ifp != r2->ifp) + return 0; + return 1; } @@ -101,20 +109,18 @@ static void *pbr_rule_alloc_intern(void *arg) return new; } -void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule, - struct interface *ifp) +void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule) { (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern); - kernel_add_pbr_rule(rule, ifp); + kernel_add_pbr_rule(rule); } -void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule, - struct interface *ifp) +void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule) { struct zebra_pbr_rule *lookup; lookup = hash_lookup(zns->rules_hash, rule); - kernel_del_pbr_rule(rule, ifp); + kernel_del_pbr_rule(rule); if (lookup) XFREE(MTYPE_TMP, lookup); @@ -127,7 +133,6 @@ void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule, * Handle success or failure of rule (un)install in the kernel. */ void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule, - struct interface *ifp, enum southbound_results res) { } @@ -135,7 +140,7 @@ void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule, /* * Handle rule delete notification from kernel. */ -int kernel_pbr_rule_del(struct zebra_pbr_rule *rule, struct interface *ifp) +int kernel_pbr_rule_del(struct zebra_pbr_rule *rule) { return 0; } diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index f5f139cbda..9983de4f22 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -86,14 +86,13 @@ struct zebra_pbr_action { struct zebra_pbr_rule { uint32_t seq; uint32_t priority; + struct interface *ifp; struct zebra_pbr_filter filter; struct zebra_pbr_action action; }; -void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule, - struct interface *ifp); -void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule, - struct interface *ifp); +void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule); +void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule); /* * Install specified rule for a specific interface. @@ -101,14 +100,12 @@ void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule, * forwarding plane may not coincide, hence the API requires a separate * rule priority - maps to preference/FRA_PRIORITY on Linux. */ -extern void kernel_add_pbr_rule(struct zebra_pbr_rule *rule, - struct interface *ifp); +extern void kernel_add_pbr_rule(struct zebra_pbr_rule *rule); /* * Uninstall specified rule for a specific interface. */ -extern void kernel_del_pbr_rule(struct zebra_pbr_rule *rule, - struct interface *ifp); +extern void kernel_del_pbr_rule(struct zebra_pbr_rule *rule); /* * Get to know existing PBR rules in the kernel - typically called at startup. @@ -119,14 +116,12 @@ extern void kernel_read_pbr_rules(struct zebra_ns *zns); * Handle success or failure of rule (un)install in the kernel. */ extern void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule, - struct interface *ifp, enum southbound_results res); /* * Handle rule delete notification from kernel. */ -extern int kernel_pbr_rule_del(struct zebra_pbr_rule *rule, - struct interface *ifp); +extern int kernel_pbr_rule_del(struct zebra_pbr_rule *rule); extern void zebra_pbr_rules_free(void *arg); extern uint32_t zebra_pbr_rules_hash_key(void *arg); diff --git a/zebra/zserv.c b/zebra/zserv.c index a56b388ec9..d05b058c7c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2592,7 +2592,6 @@ static inline void zread_rule(uint16_t command, struct zserv *client, uint16_t length, struct zebra_vrf *zvrf) { struct zebra_pbr_rule zpr; - struct interface *ifp; struct stream *s; uint32_t total, i; ifindex_t ifindex; @@ -2618,8 +2617,8 @@ static inline void zread_rule(uint16_t command, struct zserv *client, STREAM_GETL(s, zpr.action.table); STREAM_GETL(s, ifindex); - ifp = if_lookup_by_index(ifindex, VRF_UNKNOWN); - if (!ifp) { + zpr.ifp = if_lookup_by_index(ifindex, VRF_UNKNOWN); + if (!zpr.ifp) { zlog_debug("FAiled to lookup ifindex: %u", ifindex); return; } @@ -2636,7 +2635,10 @@ static inline void zread_rule(uint16_t command, struct zserv *client, if (zpr.filter.dst_port) zpr.filter.filter_bm |= PBR_FILTER_DST_PORT; - zebra_pbr_add_rule(zvrf->zns, &zpr, ifp); + if (command == ZEBRA_RULE_ADD) + zebra_pbr_add_rule(zvrf->zns, &zpr); + else + zebra_pbr_del_rule(zvrf->zns, &zpr); } stream_failure: