]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: convert ip rule installation to use dplane thread
authorJakub Urbańczyk <xthaid@gmail.com>
Sun, 24 May 2020 17:03:25 +0000 (19:03 +0200)
committerJakub Urbańczyk <xthaid@gmail.com>
Wed, 10 Jun 2020 14:18:45 +0000 (16:18 +0200)
 * Implement new dataplane operations
 * Convert existing code to use dataplane context object
 * Modify function preparing netlink message to use dataplane
   context object

Signed-off-by: Jakub Urbańczyk <xthaid@gmail.com>
zebra/rule_netlink.c
zebra/rule_socket.c
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_errors.h
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_rib.c

index a5a605f27e680d5fbd6d4f70cb9fe841f4272d51..66073042cde962e4c0198153034d25da40bb0c3d 100644 (file)
@@ -41,6 +41,7 @@
 #include "zebra/rule_netlink.h"
 #include "zebra/zebra_pbr.h"
 #include "zebra/zebra_errors.h"
+#include "zebra/zebra_dplane.h"
 
 /* definitions */
 
 /* Private functions */
 
 /* Install or uninstall specified rule for a specific interface.
- * Form netlink message and ship it. Currently, notify status after
- * waiting for netlink status.
+ * Form netlink message and ship it.
  */
-static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
+static int
+netlink_rule_update_internal(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 protocol = RTPROT_ZEBRA;
        int family;
@@ -64,11 +68,12 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
        } req;
        struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
        struct sockaddr_nl snl;
+       const char *ifname = dplane_ctx_get_ifname(ctx);
        char buf1[PREFIX_STRLEN];
        char buf2[PREFIX_STRLEN];
 
        memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
-       family = PREFIX_FAMILY(&rule->rule.filter.src_ip);
+       family = PREFIX_FAMILY(src_ip);
        bytelen = (family == AF_INET ? 4 : 16);
 
        req.n.nlmsg_type = cmd;
@@ -83,119 +88,100 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
                  FRA_PROTOCOL, &protocol, sizeof(protocol));
 
        /* rule's pref # */
-       addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority);
+       addattr32(&req.n, sizeof(req), FRA_PRIORITY, priority);
 
        /* interface on which applied */
-       addattr_l(&req.n, sizeof(req), FRA_IFNAME, rule->ifname,
-                 strlen(rule->ifname) + 1);
+       addattr_l(&req.n, sizeof(req), FRA_IFNAME, ifname, strlen(ifname) + 1);
 
        /* source IP, if specified */
-       if (IS_RULE_FILTERING_ON_SRC_IP(rule)) {
-               req.frh.src_len = rule->rule.filter.src_ip.prefixlen;
-               addattr_l(&req.n, sizeof(req), FRA_SRC,
-                         &rule->rule.filter.src_ip.u.prefix, bytelen);
+       if (filter_bm & PBR_FILTER_SRC_IP) {
+               req.frh.src_len = src_ip->prefixlen;
+               addattr_l(&req.n, sizeof(req), FRA_SRC, &src_ip->u.prefix,
+                         bytelen);
        }
        /* destination IP, if specified */
-       if (IS_RULE_FILTERING_ON_DST_IP(rule)) {
-               req.frh.dst_len = rule->rule.filter.dst_ip.prefixlen;
-               addattr_l(&req.n, sizeof(req), FRA_DST,
-                         &rule->rule.filter.dst_ip.u.prefix, bytelen);
+       if (filter_bm & PBR_FILTER_DST_IP) {
+               req.frh.dst_len = dst_ip->prefixlen;
+               addattr_l(&req.n, sizeof(req), FRA_DST, &dst_ip->u.prefix,
+                         bytelen);
        }
 
        /* fwmark, if specified */
-       if (IS_RULE_FILTERING_ON_FWMARK(rule)) {
-               addattr32(&req.n, sizeof(req), FRA_FWMARK,
-                         rule->rule.filter.fwmark);
-       }
+       if (filter_bm & PBR_FILTER_FWMARK)
+               addattr32(&req.n, sizeof(req), FRA_FWMARK, fwmark);
 
        /* Route table to use to forward, if filter criteria matches. */
-       if (rule->rule.action.table < 256)
-               req.frh.table = rule->rule.action.table;
+       if (table < 256)
+               req.frh.table = table;
        else {
                req.frh.table = RT_TABLE_UNSPEC;
-               addattr32(&req.n, sizeof(req), FRA_TABLE,
-                         rule->rule.action.table);
+               addattr32(&req.n, sizeof(req), FRA_TABLE, table);
        }
 
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug(
                        "Tx %s family %s IF %s(%u) Pref %u Fwmark %u Src %s Dst %s Table %u",
                        nl_msg_type_to_str(cmd), nl_family_to_str(family),
-                       rule->ifname, rule->rule.ifindex, rule->rule.priority,
-                       rule->rule.filter.fwmark,
-                       prefix2str(&rule->rule.filter.src_ip, buf1,
-                                  sizeof(buf1)),
-                       prefix2str(&rule->rule.filter.dst_ip, buf2,
-                                  sizeof(buf2)),
-                       rule->rule.action.table);
+                       ifname, dplane_ctx_get_ifindex(ctx), priority, fwmark,
+                       prefix2str(src_ip, buf1, sizeof(buf1)),
+                       prefix2str(dst_ip, buf2, sizeof(buf2)), table);
 
-       /* Ship off the message.
-        * Note: Currently, netlink_talk() is a blocking call which returns
-        * back the status.
-        */
        memset(&snl, 0, sizeof(snl));
        snl.nl_family = AF_NETLINK;
        return netlink_talk(netlink_talk_filter, &req.n,
                            &zns->netlink_cmd, zns, 0);
 }
 
-
 /* Public functions */
-/*
- * Install specified rule for a specific interface. The preference is what
- * goes in the rule to denote relative ordering; it may or may not be the
- * same as the rule's user-defined sequence number.
- */
-enum zebra_dplane_result kernel_add_pbr_rule(struct zebra_pbr_rule *rule)
-{
-       int ret = 0;
-
-       ret = netlink_rule_update(RTM_NEWRULE, rule);
-       kernel_pbr_rule_add_del_status(rule,
-                                      (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
-                                             : ZEBRA_DPLANE_INSTALL_FAILURE);
-
-       return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
 
 /*
- * Uninstall specified rule for a specific interface.
+ * Add, update or delete a rule from the
+ * kernel, using info from a dataplane context.
  */
-enum zebra_dplane_result kernel_del_pbr_rule(struct zebra_pbr_rule *rule)
+enum zebra_dplane_result kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx)
 {
-       int ret = 0;
-
-       ret = netlink_rule_update(RTM_DELRULE, rule);
-       kernel_pbr_rule_add_del_status(rule,
-                                      (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS
-                                             : ZEBRA_DPLANE_DELETE_FAILURE);
-
-       return ZEBRA_DPLANE_REQUEST_SUCCESS;
-}
+       enum dplane_op_e op;
+       int cmd;
+       int ret;
 
-/*
- * Update specified rule for a specific interface.
- */
-enum zebra_dplane_result kernel_update_pbr_rule(struct zebra_pbr_rule *old_rule,
-                                               struct zebra_pbr_rule *new_rule)
-{
-       int ret = 0;
+       op = dplane_ctx_get_op(ctx);
+       if (op == DPLANE_OP_RULE_ADD || op == DPLANE_OP_RULE_UPDATE)
+               cmd = RTM_NEWRULE;
+       else if (op == DPLANE_OP_RULE_DELETE)
+               cmd = RTM_DELRULE;
+       else {
+               flog_err(
+                       EC_ZEBRA_PBR_RULE_UPDATE,
+                       "Context received for kernel rule update with incorrect OP code (%u)",
+                       op);
+               return ZEBRA_DPLANE_REQUEST_FAILURE;
+       }
 
-       /* Add the new, updated one */
-       ret = netlink_rule_update(RTM_NEWRULE, new_rule);
+       ret = netlink_rule_update_internal(
+               cmd, ctx, dplane_ctx_rule_get_filter_bm(ctx),
+               dplane_ctx_rule_get_priority(ctx),
+               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));
 
        /**
         * Delete the old one.
         *
         * Don't care about this result right?
         */
-       netlink_rule_update(RTM_DELRULE, old_rule);
-
-       kernel_pbr_rule_add_del_status(new_rule,
-                                      (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS
-                                             : ZEBRA_DPLANE_INSTALL_FAILURE);
-
-       return ZEBRA_DPLANE_REQUEST_SUCCESS;
+       if (op == DPLANE_OP_RULE_UPDATE)
+               netlink_rule_update_internal(
+                       RTM_DELRULE, ctx,
+                       dplane_ctx_rule_get_old_filter_bm(ctx),
+                       dplane_ctx_rule_get_old_priority(ctx),
+                       dplane_ctx_rule_get_old_table(ctx),
+                       dplane_ctx_rule_get_old_src_ip(ctx),
+                       dplane_ctx_rule_get_old_dst_ip(ctx),
+                       dplane_ctx_rule_get_old_fwmark(ctx));
+
+
+       return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS
+                        : ZEBRA_DPLANE_REQUEST_FAILURE);
 }
 
 /*
@@ -296,14 +282,16 @@ int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                 * It should have been flushed on a previous shutdown.
                 */
                if (startup && proto == RTPROT_ZEBRA) {
-                       int ret;
+                       enum zebra_dplane_result ret;
 
-                       ret = netlink_rule_update(RTM_DELRULE, &rule);
+                       ret = dplane_pbr_rule_delete(&rule);
 
                        zlog_debug(
                                "%s: %s leftover rule: family %s IF %s(%u) Pref %u Src %s Dst %s Table %u",
                                __func__,
-                               ((ret == 0) ? "Removed" : "Failed to remove"),
+                               ((ret == ZEBRA_DPLANE_REQUEST_FAILURE)
+                                        ? "Failed to remove"
+                                        : "Removed"),
                                nl_family_to_str(frh->family), rule.ifname,
                                rule.rule.ifindex, rule.rule.priority,
                                prefix2str(&rule.rule.filter.src_ip, buf1,
index 219fa7de6f273dbfe3bb626b1a42fc7721356a9e..e629017bdf88ae79599072e71659d0e825870a35 100644 (file)
 #include "zebra/zebra_pbr.h"
 #include "zebra/zebra_errors.h"
 
-enum zebra_dplane_result kernel_add_pbr_rule(struct zebra_pbr_rule *rule)
+enum zebra_dplane_result kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx)
 {
        flog_err(EC_LIB_UNAVAILABLE, "%s not Implemented for this platform",
                 __func__);
        return ZEBRA_DPLANE_REQUEST_FAILURE;
 }
 
-enum zebra_dplane_result kernel_del_pbr_rule(struct zebra_pbr_rule *rule)
-{
-       flog_err(EC_LIB_UNAVAILABLE, "%s not Implemented for this platform",
-                __func__);
-       return ZEBRA_DPLANE_REQUEST_FAILURE;
-}
-
-enum zebra_dplane_result kernel_update_pbr_rule(struct zebra_pbr_rule *old_rule,
-                                               struct zebra_pbr_rule *new_rule)
-{
-       flog_err(EC_LIB_UNAVAILABLE, "%s not Implemented for this platform",
-                __PRETTY_FUNCTION__);
-       return ZEBRA_DPLANE_REQUEST_FAILURE;
-}
-
 #endif
index cea8edf75242b99e1269960dace20d26b11b9607..a40aa8b64345cc5e921b0ffa629d1d8edef6b7c7 100644 (file)
@@ -785,7 +785,7 @@ int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
                                      note));
 }
 
-void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
+void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
                             enum zapi_rule_notify_owner note)
 {
        struct listnode *node;
@@ -793,10 +793,11 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
        struct stream *s;
 
        if (IS_ZEBRA_DEBUG_PACKET)
-               zlog_debug("%s: Notifying %u", __func__, rule->rule.unique);
+               zlog_debug("%s: Notifying %u", __func__,
+                          dplane_ctx_rule_get_unique(ctx));
 
        for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
-               if (rule->sock == client->sock)
+               if (dplane_ctx_rule_get_sock(ctx) == client->sock)
                        break;
        }
 
@@ -807,10 +808,10 @@ void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
 
        zclient_create_header(s, ZEBRA_RULE_NOTIFY_OWNER, VRF_DEFAULT);
        stream_put(s, &note, sizeof(note));
-       stream_putl(s, rule->rule.seq);
-       stream_putl(s, rule->rule.priority);
-       stream_putl(s, rule->rule.unique);
-       stream_putl(s, rule->rule.ifindex);
+       stream_putl(s, dplane_ctx_rule_get_seq(ctx));
+       stream_putl(s, dplane_ctx_rule_get_priority(ctx));
+       stream_putl(s, dplane_ctx_rule_get_unique(ctx));
+       stream_putl(s, dplane_ctx_get_ifindex(ctx));
 
        stream_putw_at(s, 0, stream_get_endp(s));
 
index 6d655e11aadd8cf7f79343f3aada4de31795da74..eb50e3c41014d0fa325bef21d20486b126ac73ec 100644 (file)
@@ -81,7 +81,7 @@ extern int zsend_route_notify_owner(struct route_entry *re,
 extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
                                        enum zapi_route_notify_owner note);
 
-extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
+extern void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
                                    enum zapi_rule_notify_owner note);
 extern void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
                                     enum zapi_ipset_notify_owner note);
index 6c1bfaa98c4f58a73a5ce9b13ae0e5bd85abfcf2..eb3d48d78427a7a65cb8c90bd6034b67084a5013 100644 (file)
@@ -35,6 +35,7 @@
 #include "zebra/zebra_mpls.h"
 #include "zebra/rt.h"
 #include "zebra/debug.h"
+#include "zebra/zebra_pbr.h"
 
 /* Memory type for context blocks */
 DEFINE_MTYPE_STATIC(ZEBRA, DP_CTX, "Zebra DPlane Ctx")
@@ -2070,6 +2071,76 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
        return AOK;
 }
 
+/**
+ * dplane_ctx_rule_init_single() - Initialize a dataplane representation of a
+ * PBR rule.
+ *
+ * @dplane_rule:       Dataplane internal representation of a rule
+ * @rule:                      PBR rule
+ */
+static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule,
+                                       struct zebra_pbr_rule *rule)
+{
+       dplane_rule->priority = rule->rule.priority;
+       dplane_rule->table = rule->rule.action.table;
+
+       dplane_rule->filter_bm = rule->rule.filter.filter_bm;
+       dplane_rule->fwmark = rule->rule.filter.fwmark;
+       prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
+       prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
+}
+
+/**
+ * dplane_ctx_rule_init() - Initialize a context block for a PBR rule update.
+ *
+ * @ctx:               Dataplane context to init
+ * @op:                        Operation being performed
+ * @new_rule:  PBR rule
+ *
+ * Return:     Result status
+ */
+static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx,
+                               enum dplane_op_e op,
+                               struct zebra_pbr_rule *new_rule,
+                               struct zebra_pbr_rule *old_rule)
+{
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf1[PREFIX_STRLEN];
+               char buf2[PREFIX_STRLEN];
+
+               zlog_debug(
+                       "init dplane ctx %s: IF %s(%u) Prio %u Fwmark %u Src %s Dst %s Table %u",
+                       dplane_op2str(op), new_rule->ifname,
+                       new_rule->rule.ifindex, new_rule->rule.priority,
+                       new_rule->rule.filter.fwmark,
+                       prefix2str(&new_rule->rule.filter.src_ip, buf1,
+                                  sizeof(buf1)),
+                       prefix2str(&new_rule->rule.filter.dst_ip, buf2,
+                                  sizeof(buf2)),
+                       new_rule->rule.action.table);
+       }
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+       dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT),
+                          op == DPLANE_OP_RULE_UPDATE);
+
+       ctx->zd_vrf_id = new_rule->vrf_id;
+       memcpy(ctx->zd_ifname, new_rule->ifname, sizeof(new_rule->ifname));
+       ctx->zd_ifindex = new_rule->rule.ifindex;
+
+       ctx->u.rule.sock = new_rule->sock;
+       ctx->u.rule.unique = new_rule->rule.unique;
+       ctx->u.rule.seq = new_rule->rule.seq;
+
+       dplane_ctx_rule_init_single(&ctx->u.rule.new, new_rule);
+       if (op == DPLANE_OP_RULE_UPDATE)
+               dplane_ctx_rule_init_single(&ctx->u.rule.old, old_rule);
+
+       return AOK;
+}
+
 /*
  * Enqueue a new update,
  * and ensure an event is active for the dataplane pthread.
@@ -2996,6 +3067,56 @@ neigh_update_internal(enum dplane_op_e op,
        return result;
 }
 
+/*
+ * Common helper api for PBR rule updates
+ */
+static enum zebra_dplane_result
+rule_update_internal(enum dplane_op_e op, struct zebra_pbr_rule *new_rule,
+                    struct zebra_pbr_rule *old_rule)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       struct zebra_dplane_ctx *ctx;
+       int ret;
+
+       ctx = dplane_ctx_alloc();
+
+       ret = dplane_ctx_rule_init(ctx, op, new_rule, old_rule);
+       if (ret != AOK)
+               goto done;
+
+       ret = dplane_update_enqueue(ctx);
+
+done:
+       atomic_fetch_add_explicit(&zdplane_info.dg_rules_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               atomic_fetch_add_explicit(&zdplane_info.dg_rule_errors, 1,
+                                         memory_order_relaxed);
+               dplane_ctx_free(&ctx);
+       }
+
+       return result;
+}
+
+enum zebra_dplane_result dplane_pbr_rule_add(struct zebra_pbr_rule *rule)
+{
+       return rule_update_internal(DPLANE_OP_RULE_ADD, rule, NULL);
+}
+
+enum zebra_dplane_result dplane_pbr_rule_delete(struct zebra_pbr_rule *rule)
+{
+       return rule_update_internal(DPLANE_OP_RULE_DELETE, rule, NULL);
+}
+
+enum zebra_dplane_result dplane_pbr_rule_update(struct zebra_pbr_rule *old_rule,
+                                               struct zebra_pbr_rule *new_rule)
+{
+       return rule_update_internal(DPLANE_OP_RULE_UPDATE, new_rule, old_rule);
+}
+
 /*
  * Handler for 'show dplane'
  */
@@ -3561,6 +3682,29 @@ kernel_dplane_neigh_update(struct zebra_dplane_ctx *ctx)
        return res;
 }
 
+/*
+ *  Handler for kernel PBR rule updates
+ */
+static enum zebra_dplane_result
+kernel_dplane_rule_update(struct zebra_dplane_ctx *ctx)
+{
+       enum zebra_dplane_result res;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+               zlog_debug("Dplane rule update op %s, if %s(%u), ctx %p",
+                          dplane_op2str(dplane_ctx_get_op(ctx)),
+                          dplane_ctx_get_ifname(ctx),
+                          dplane_ctx_get_ifindex(ctx), ctx);
+
+       res = kernel_pbr_rule_update(ctx);
+
+       if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+               atomic_fetch_add_explicit(&zdplane_info.dg_rule_errors, 1,
+                                         memory_order_relaxed);
+
+       return res;
+}
+
 /*
  * Kernel provider callback
  */
@@ -3634,6 +3778,12 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
                        res = kernel_dplane_neigh_update(ctx);
                        break;
 
+               case DPLANE_OP_RULE_ADD:
+               case DPLANE_OP_RULE_DELETE:
+               case DPLANE_OP_RULE_UPDATE:
+                       res = kernel_dplane_rule_update(ctx);
+                       break;
+
                /* Ignore 'notifications' - no-op */
                case DPLANE_OP_SYS_ROUTE_ADD:
                case DPLANE_OP_SYS_ROUTE_DELETE:
index 164fce75bc02dbc2170cee95d392c3ffef5fa56e..c93b95a6ad0871b8ea6398dfb013d6d02684f784 100644 (file)
@@ -535,6 +535,21 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
                                            const struct in_addr *ip,
                                            vni_t vni);
 
+/* Forward ref of zebra_pbr_rule */
+struct zebra_pbr_rule;
+
+/*
+ * Enqueue policy based routing rule for the dataplane.
+ * It is possible that the user-defined sequence number and the one in the
+ * forwarding plane may not coincide, hence the API requires a separate
+ * rule priority - maps to preference/FRA_PRIORITY on Linux.
+ */
+enum zebra_dplane_result dplane_pbr_rule_add(struct zebra_pbr_rule *rule);
+enum zebra_dplane_result dplane_pbr_rule_delete(struct zebra_pbr_rule *rule);
+enum zebra_dplane_result
+dplane_pbr_rule_update(struct zebra_pbr_rule *old_rule,
+                      struct zebra_pbr_rule *new_rule);
+
 /* Encode route information into data plane context. */
 int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
                          struct route_node *rn, struct route_entry *re);
index 395004d0bb28377a8f7cddcae5b56eadf0e97771..5f2a7a12c67e0128b333de4c736f0bd6b27708bf 100644 (file)
@@ -77,6 +77,7 @@ enum zebra_log_refs {
        EC_ZEBRA_NHG_FIB_UPDATE,
        EC_ZEBRA_IF_LOOKUP_FAILED,
        EC_ZEBRA_NS_NO_DEFAULT,
+       EC_ZEBRA_PBR_RULE_UPDATE,
        /* warnings */
        EC_ZEBRA_NS_NOTIFY_READ,
        EC_ZEBRAING_LM_PROTO_MISMATCH,
index 62cbcbda4b244731e8e04393235970955b90a8e6..c5a7795273a7ae6757aae363dd55c54a72599e5e 100644 (file)
@@ -131,7 +131,7 @@ void zebra_pbr_rules_free(void *arg)
 
        rule = (struct zebra_pbr_rule *)arg;
 
-       (void)kernel_del_pbr_rule(rule);
+       (void)dplane_pbr_rule_delete(rule);
        XFREE(MTYPE_TMP, rule);
 }
 
@@ -460,7 +460,7 @@ void zebra_pbr_add_rule(struct zebra_pbr_rule *rule)
 
        /* If found, this is an update */
        if (found) {
-               (void)kernel_update_pbr_rule(found, rule);
+               (void)dplane_pbr_rule_update(found, rule);
 
                if (pbr_rule_release(found))
                        zlog_debug(
@@ -468,12 +468,12 @@ void zebra_pbr_add_rule(struct zebra_pbr_rule *rule)
                                __PRETTY_FUNCTION__);
 
        } else
-               (void)kernel_add_pbr_rule(rule);
+               (void)dplane_pbr_rule_add(rule);
 }
 
 void zebra_pbr_del_rule(struct zebra_pbr_rule *rule)
 {
-       (void)kernel_del_pbr_rule(rule);
+       (void)dplane_pbr_rule_delete(rule);
 
        if (pbr_rule_release(rule))
                zlog_debug("%s: Rule being deleted we know nothing about",
@@ -486,7 +486,7 @@ static void zebra_pbr_cleanup_rules(struct hash_bucket *b, void *data)
        int *sock = data;
 
        if (rule->sock == *sock) {
-               (void)kernel_del_pbr_rule(rule);
+               (void)dplane_pbr_rule_delete(rule);
                if (hash_release(zrouter.rules_hash, rule))
                        XFREE(MTYPE_TMP, rule);
                else
@@ -735,25 +735,29 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
 /*
  * Handle success or failure of rule (un)install in the kernel.
  */
-void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
-                                   enum zebra_dplane_status res)
+void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx)
 {
-       switch (res) {
-       case ZEBRA_DPLANE_INSTALL_SUCCESS:
-               zsend_rule_notify_owner(rule, ZAPI_RULE_INSTALLED);
-               break;
-       case ZEBRA_DPLANE_INSTALL_FAILURE:
-               zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_INSTALL);
-               break;
-       case ZEBRA_DPLANE_DELETE_SUCCESS:
-               zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
-               break;
-       case ZEBRA_DPLANE_DELETE_FAILURE:
-               zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_REMOVE);
-               break;
-       case ZEBRA_DPLANE_STATUS_NONE:
-               break;
-       }
+       enum zebra_dplane_result res;
+       enum dplane_op_e op;
+
+       res = dplane_ctx_get_status(ctx);
+       op = dplane_ctx_get_op(ctx);
+       if (op == DPLANE_OP_RULE_ADD || op == DPLANE_OP_RULE_UPDATE)
+               zsend_rule_notify_owner(ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
+                                                    ? ZAPI_RULE_INSTALLED
+                                                    : ZAPI_RULE_FAIL_INSTALL);
+       else if (op == DPLANE_OP_RULE_DELETE)
+               zsend_rule_notify_owner(ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
+                                                    ? ZAPI_RULE_REMOVED
+                                                    : ZAPI_RULE_FAIL_REMOVE);
+       else
+               flog_err(
+                       EC_ZEBRA_PBR_RULE_UPDATE,
+                       "Context received in pbr rule dplane result handler with incorrect OP code (%u)",
+                       op);
+
+
+       dplane_ctx_fini(&ctx);
 }
 
 /*
index 83797b95219b15922b39976fb47944fc1d9aa674..4bc0f400376d7ec9d67d007e0b06e5cca8e09411 100644 (file)
@@ -170,24 +170,11 @@ void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable);
 void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable);
 
 /*
- * Install specified rule for a specific interface.
- * It is possible that the user-defined sequence number and the one in the
- * forwarding plane may not coincide, hence the API requires a separate
- * rule priority - maps to preference/FRA_PRIORITY on Linux.
- */
-extern enum zebra_dplane_result kernel_add_pbr_rule(struct zebra_pbr_rule *rule);
-
-/*
- * Uninstall specified rule for a specific interface.
- */
-extern enum zebra_dplane_result kernel_del_pbr_rule(struct zebra_pbr_rule *rule);
-
-/*
- * Update specified rule for a specific interface.
+ * Add, update or delete a rule from the
+ * kernel, using info from a dataplane context.
  */
 extern enum zebra_dplane_result
-kernel_update_pbr_rule(struct zebra_pbr_rule *old_rule,
-                      struct zebra_pbr_rule *new_rule);
+kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx);
 
 /*
  * Get to know existing PBR rules in the kernel - typically called at startup.
@@ -197,8 +184,7 @@ 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,
-                                          enum zebra_dplane_status res);
+extern void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx);
 
 /*
  * Handle success or failure of ipset kinds (un)install in the kernel.
index 0fc716db17925b0f21a29ffb9d7ed0e556e4e3b1..75619520dc170426e669833a00de7b2bbe2e0e7f 100644 (file)
@@ -3583,6 +3583,12 @@ static int rib_process_dplane_results(struct thread *thread)
                                zebra_vxlan_handle_result(ctx);
                                break;
 
+                       case DPLANE_OP_RULE_ADD:
+                       case DPLANE_OP_RULE_DELETE:
+                       case DPLANE_OP_RULE_UPDATE:
+                               zebra_pbr_dplane_result(ctx);
+                               break;
+
                        /* Some op codes not handled here */
                        case DPLANE_OP_ADDR_INSTALL:
                        case DPLANE_OP_ADDR_UNINSTALL: