]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: move ipset and ipset_entry to zebra dplane contexts 8124/head
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 17 Feb 2021 10:43:52 +0000 (11:43 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 10 Mar 2021 13:57:32 +0000 (14:57 +0100)
like it has been done for iptable contexts, a zebra dplane context is
created for each ipset/ipset entry event. The zebra_dplane_ctx job is
then enqueued and processed by separate thread. Like it has been done
for zebra_pbr_iptable context, the ipset and ipset entry contexts are
encapsulated into an union of structures in zebra_dplane_ctx.

There is a specificity in that when storing ipset_entry structure, there
was a backpointer pointer to the ipset structure that is necessary
to get some complementary information before calling the hook. The
proposal is to use an ipset_entry_info structure next to the ipset_entry,
in the zebra_dplane context. That information is used for ipset_entry
processing. The ipset name and the ipset type are the only fields
 necessary.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
lib/zclient.c
lib/zclient.h
zebra/kernel_netlink.c
zebra/zapi_msg.c
zebra/zapi_msg.h
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_nhg.c
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_rib.c

index 20c285cf7f1d73592762ac85d230a98248033128..6ce2113b9169dba8255b73ac5e0e863ba24aa03c 100644 (file)
@@ -1551,15 +1551,16 @@ bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
                              enum zapi_ipset_notify_owner *note)
 {
        uint32_t uni;
+       uint16_t notew;
 
-       STREAM_GET(note, s, sizeof(*note));
+       STREAM_GETW(s, notew);
 
        STREAM_GETL(s, uni);
 
        if (zclient_debug)
                zlog_debug("%s: %u", __func__, uni);
        *unique = uni;
-
+       *note = (enum zapi_ipset_notify_owner)notew;
        return true;
 
 stream_failure:
@@ -1571,8 +1572,9 @@ bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
                                    enum zapi_ipset_entry_notify_owner *note)
 {
        uint32_t uni;
+       uint16_t notew;
 
-       STREAM_GET(note, s, sizeof(*note));
+       STREAM_GETW(s, notew);
 
        STREAM_GETL(s, uni);
 
@@ -1581,6 +1583,7 @@ bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
        if (zclient_debug)
                zlog_debug("%s: %u", __func__, uni);
        *unique = uni;
+       *note = (enum zapi_ipset_entry_notify_owner)notew;
 
        return true;
 
@@ -1593,14 +1596,16 @@ bool zapi_iptable_notify_decode(struct stream *s,
                enum zapi_iptable_notify_owner *note)
 {
        uint32_t uni;
+       uint16_t notew;
 
-       STREAM_GET(note, s, sizeof(*note));
+       STREAM_GETW(s, notew);
 
        STREAM_GETL(s, uni);
 
        if (zclient_debug)
                zlog_debug("%s: %u", __func__, uni);
        *unique = uni;
+       *note = (enum zapi_iptable_notify_owner)notew;
 
        return true;
 
index cf52ea91a0019e1716395b3d49d95a270c1a1cec..43197534a8f6c91a5bc2e8e908bee2e164185a3a 100644 (file)
@@ -713,21 +713,21 @@ enum ipset_type {
 };
 
 enum zapi_ipset_notify_owner {
-       ZAPI_IPSET_FAIL_INSTALL,
+       ZAPI_IPSET_FAIL_INSTALL = 0,
        ZAPI_IPSET_INSTALLED,
        ZAPI_IPSET_REMOVED,
        ZAPI_IPSET_FAIL_REMOVE,
 };
 
 enum zapi_ipset_entry_notify_owner {
-       ZAPI_IPSET_ENTRY_FAIL_INSTALL,
+       ZAPI_IPSET_ENTRY_FAIL_INSTALL = 0,
        ZAPI_IPSET_ENTRY_INSTALLED,
        ZAPI_IPSET_ENTRY_REMOVED,
        ZAPI_IPSET_ENTRY_FAIL_REMOVE,
 };
 
 enum zapi_iptable_notify_owner {
-       ZAPI_IPTABLE_FAIL_INSTALL,
+       ZAPI_IPTABLE_FAIL_INSTALL = 0,
        ZAPI_IPTABLE_INSTALLED,
        ZAPI_IPTABLE_REMOVED,
        ZAPI_IPTABLE_FAIL_REMOVE,
index 8dd0c14d5da0cc1efd61a7a3acd60352cbb6bd20..aa19b180890cccf0a3eb3c84b33ac8d79c4ffc14 100644 (file)
@@ -1352,6 +1352,10 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
 
        case DPLANE_OP_IPTABLE_ADD:
        case DPLANE_OP_IPTABLE_DELETE:
+       case DPLANE_OP_IPSET_ADD:
+       case DPLANE_OP_IPSET_DELETE:
+       case DPLANE_OP_IPSET_ENTRY_ADD:
+       case DPLANE_OP_IPSET_ENTRY_DELETE:
                return FRR_NETLINK_ERROR;
 
        case DPLANE_OP_NONE:
index 92a11cc4bfe392c2d2f52976700be7271038b26b..9f5adfa40993387e2daeeda9ee52aa87bbc9106c 100644 (file)
@@ -866,18 +866,24 @@ void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
        zserv_send_message(client, s);
 }
 
-void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
-                             enum zapi_ipset_notify_owner note)
+void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
+                               uint16_t note)
 {
        struct listnode *node;
        struct zserv *client;
        struct stream *s;
+       struct zebra_pbr_iptable ipt;
+       uint16_t cmd = ZEBRA_IPTABLE_NOTIFY_OWNER;
+
+       if (!dplane_ctx_get_pbr_iptable(ctx, &ipt))
+               return;
 
        if (IS_ZEBRA_DEBUG_PACKET)
-               zlog_debug("%s: Notifying %u", __func__, ipset->unique);
+               zlog_debug("%s: Notifying %s id %u note %u", __func__,
+                          zserv_command_string(cmd), ipt.unique, note);
 
        for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
-               if (ipset->sock == client->sock)
+               if (ipt.sock == client->sock)
                        break;
        }
 
@@ -888,25 +894,30 @@ void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
 
        zclient_create_header(s, cmd, VRF_DEFAULT);
        stream_put(s, &note, sizeof(note));
-       stream_putl(s, ipset->unique);
-       stream_put(s, ipset->ipset_name, ZEBRA_IPSET_NAME_SIZE);
+       stream_putl(s, ipt.unique);
+       stream_put(s, ipt.ipset_name, ZEBRA_IPSET_NAME_SIZE);
        stream_putw_at(s, 0, stream_get_endp(s));
 
        zserv_send_message(client, s);
 }
 
-void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
-                                   enum zapi_ipset_entry_notify_owner note)
+void zsend_ipset_notify_owner(const struct zebra_dplane_ctx *ctx, uint16_t note)
 {
        struct listnode *node;
        struct zserv *client;
        struct stream *s;
+       struct zebra_pbr_ipset ipset;
+       uint16_t cmd = ZEBRA_IPSET_NOTIFY_OWNER;
+
+       if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
+               return;
 
        if (IS_ZEBRA_DEBUG_PACKET)
-               zlog_debug("%s: Notifying %u", __func__, ipset->unique);
+               zlog_debug("%s: Notifying %s id %u note %u", __func__,
+                          zserv_command_string(cmd), ipset.unique, note);
 
        for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
-               if (ipset->sock == client->sock)
+               if (ipset.sock == client->sock)
                        break;
        }
 
@@ -915,33 +926,36 @@ void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
 
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
 
-       zclient_create_header(s, ZEBRA_IPSET_ENTRY_NOTIFY_OWNER, VRF_DEFAULT);
+       zclient_create_header(s, cmd, VRF_DEFAULT);
        stream_put(s, &note, sizeof(note));
-       stream_putl(s, ipset->unique);
-       stream_put(s, ipset->backpointer->ipset_name, ZEBRA_IPSET_NAME_SIZE);
+       stream_putl(s, ipset.unique);
+       stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
        stream_putw_at(s, 0, stream_get_endp(s));
 
        zserv_send_message(client, s);
 }
 
-void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
-                               uint16_t note)
+void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
+                                   uint16_t note)
 {
        struct listnode *node;
        struct zserv *client;
        struct stream *s;
-       struct zebra_pbr_iptable ipt;
-       uint16_t cmd = ZEBRA_IPTABLE_NOTIFY_OWNER;
+       struct zebra_pbr_ipset_entry ipent;
+       struct zebra_pbr_ipset ipset;
+       uint16_t cmd = ZEBRA_IPSET_ENTRY_NOTIFY_OWNER;
 
-       if (!dplane_ctx_get_pbr_iptable(ctx, &ipt))
+       if (!dplane_ctx_get_pbr_ipset_entry(ctx, &ipent))
+               return;
+       if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
                return;
 
        if (IS_ZEBRA_DEBUG_PACKET)
                zlog_debug("%s: Notifying %s id %u note %u", __func__,
-                          zserv_command_string(cmd), ipt.unique, note);
+                          zserv_command_string(cmd), ipent.unique, note);
 
        for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
-               if (ipt.sock == client->sock)
+               if (ipent.sock == client->sock)
                        break;
        }
 
@@ -952,7 +966,8 @@ void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
 
        zclient_create_header(s, cmd, VRF_DEFAULT);
        stream_put(s, &note, sizeof(note));
-       stream_putl(s, ipt.unique);
+       stream_putl(s, ipent.unique);
+       stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
        stream_putw_at(s, 0, stream_get_endp(s));
 
        zserv_send_message(client, s);
index 2401db4d185293e1ad1ea1b4edc3f25a6da659cf..023b9f74a8fb6ba1426eb1909a69a854ebbc55e6 100644 (file)
@@ -84,13 +84,13 @@ extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
 
 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);
-extern void
-zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
-                              enum zapi_ipset_entry_notify_owner note);
+
 extern void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
-                                      enum zapi_iptable_notify_owner note);
+                                      uint16_t note);
+extern void zsend_ipset_notify_owner(const struct zebra_dplane_ctx *ctx,
+                                    uint16_t note);
+extern void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
+                                          uint16_t note);
 extern bool zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
                                   const unsigned int nexthop_num);
 
index b9e6df2a7a96b39faacdae41113c239a63da63d7..82546ce18843b0edbe3b7fd44f1c4278d2c4ab11 100644 (file)
@@ -42,7 +42,7 @@
 DEFINE_MTYPE_STATIC(ZEBRA, DP_CTX, "Zebra DPlane Ctx")
 DEFINE_MTYPE_STATIC(ZEBRA, DP_INTF, "Zebra DPlane Intf")
 DEFINE_MTYPE_STATIC(ZEBRA, DP_PROV, "Zebra DPlane Provider")
-DEFINE_MTYPE_STATIC(ZEBRA, DP_IFACE, "Zebra DPlane IFACE")
+DEFINE_MTYPE_STATIC(ZEBRA, DP_NETFILTER, "Zebra Netfilter Internal Object")
 
 #ifndef AOK
 #  define AOK 0
@@ -309,6 +309,11 @@ struct zebra_dplane_ctx {
                struct dplane_neigh_info neigh;
                struct dplane_rule_info rule;
                struct zebra_pbr_iptable iptable;
+               struct zebra_pbr_ipset ipset;
+               union {
+                       struct zebra_pbr_ipset_entry entry;
+                       struct zebra_pbr_ipset_info info;
+               } ipset_entry;
        } u;
 
        /* Namespace info, used especially for netlink kernel communication */
@@ -442,6 +447,12 @@ static struct zebra_dplane_globals {
 
        _Atomic uint32_t dg_iptable_in;
        _Atomic uint32_t dg_iptable_errors;
+
+       _Atomic uint32_t dg_ipset_in;
+       _Atomic uint32_t dg_ipset_errors;
+       _Atomic uint32_t dg_ipset_entry_in;
+       _Atomic uint32_t dg_ipset_entry_errors;
+
        /* Dataplane pthread */
        struct frr_pthread *dg_pthread;
 
@@ -660,8 +671,13 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_NEIGH_DISCOVER:
        case DPLANE_OP_BR_PORT_UPDATE:
        case DPLANE_OP_NONE:
+       case DPLANE_OP_IPSET_ADD:
+       case DPLANE_OP_IPSET_DELETE:
                break;
 
+       case DPLANE_OP_IPSET_ENTRY_ADD:
+       case DPLANE_OP_IPSET_ENTRY_DELETE:
+               break;
        case DPLANE_OP_IPTABLE_ADD:
        case DPLANE_OP_IPTABLE_DELETE:
                if (ctx->u.iptable.interface_name_list) {
@@ -674,7 +690,7 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
                                LISTNODE_DETACH(
                                        ctx->u.iptable.interface_name_list,
                                        node);
-                               XFREE(MTYPE_DP_IFACE, ifname);
+                               XFREE(MTYPE_DP_NETFILTER, ifname);
                        }
                        list_delete(&ctx->u.iptable.interface_name_list);
                }
@@ -923,6 +939,18 @@ const char *dplane_op2str(enum dplane_op_e op)
        case DPLANE_OP_IPTABLE_DELETE:
                ret = "IPTABLE_DELETE";
                break;
+       case DPLANE_OP_IPSET_ADD:
+               ret = "IPSET_ADD";
+               break;
+       case DPLANE_OP_IPSET_DELETE:
+               ret = "IPSET_DELETE";
+               break;
+       case DPLANE_OP_IPSET_ENTRY_ADD:
+               ret = "IPSET_ENTRY_ADD";
+               break;
+       case DPLANE_OP_IPSET_ENTRY_DELETE:
+               ret = "IPSET_ENTRY_DELETE";
+               break;
        }
 
        return ret;
@@ -1882,6 +1910,35 @@ dplane_ctx_get_pbr_iptable(const struct zebra_dplane_ctx *ctx,
        return true;
 }
 
+bool dplane_ctx_get_pbr_ipset(const struct zebra_dplane_ctx *ctx,
+                             struct zebra_pbr_ipset *ipset)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       if (!ipset)
+               return false;
+       if (ctx->zd_op == DPLANE_OP_IPSET_ENTRY_ADD ||
+           ctx->zd_op == DPLANE_OP_IPSET_ENTRY_DELETE) {
+               memset(ipset, 0, sizeof(struct zebra_pbr_ipset));
+               ipset->type = ctx->u.ipset_entry.info.type;
+               memcpy(&ipset->ipset_name, &ctx->u.ipset_entry.info.ipset_name,
+                      ZEBRA_IPSET_NAME_SIZE);
+       } else
+               memcpy(ipset, &ctx->u.ipset, sizeof(struct zebra_pbr_ipset));
+       return true;
+}
+
+bool dplane_ctx_get_pbr_ipset_entry(const struct zebra_dplane_ctx *ctx,
+                                   struct zebra_pbr_ipset_entry *entry)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       if (!entry)
+               return false;
+       memcpy(entry, &ctx->u.ipset_entry.entry, sizeof(struct zebra_pbr_ipset_entry));
+       return true;
+}
+
 /*
  * End of dplane context accessors
  */
@@ -2477,12 +2534,86 @@ static int dplane_ctx_iptable_init(struct zebra_dplane_ctx *ctx,
                for (ALL_LIST_ELEMENTS_RO(iptable->interface_name_list, node,
                                          ifname)) {
                        listnode_add(ctx->u.iptable.interface_name_list,
-                                    XSTRDUP(MTYPE_DP_IFACE, ifname));
+                                    XSTRDUP(MTYPE_DP_NETFILTER, ifname));
                }
        }
        return AOK;
 }
 
+/**
+ * dplane_ctx_ipset_init() - Initialize a context block for a PBR ipset update.
+ *
+ * @ctx:               Dataplane context to init
+ * @op:                        Operation being performed
+ * @new_rule:          PBR ipset
+ *
+ * Return:     Result status
+ */
+static int dplane_ctx_ipset_init(struct zebra_dplane_ctx *ctx,
+                                enum dplane_op_e op,
+                                struct zebra_pbr_ipset *ipset)
+{
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               zlog_debug("init dplane ctx %s: %s Unique %u Family %s Type %s",
+                          dplane_op2str(op), ipset->ipset_name, ipset->unique,
+                          family2str(ipset->family),
+                          zebra_pbr_ipset_type2str(ipset->type));
+       }
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+       dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
+       ctx->zd_is_update = false;
+
+       ctx->zd_vrf_id = ipset->vrf_id;
+
+       memcpy(&ctx->u.ipset, ipset, sizeof(struct zebra_pbr_ipset));
+       return AOK;
+}
+
+/**
+ * dplane_ctx_ipset_entry_init() - Initialize a context block for a PBR ipset
+ * update.
+ *
+ * @ctx:               Dataplane context to init
+ * @op:                        Operation being performed
+ * @new_rule:  PBR ipset
+ *
+ * Return:     Result status
+ */
+static int
+dplane_ctx_ipset_entry_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
+                           struct zebra_pbr_ipset_entry *ipset_entry)
+{
+       struct zebra_pbr_ipset *ipset;
+
+       ipset = ipset_entry->backpointer;
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               zlog_debug("init dplane ctx %s: %s Unique %u filter %u",
+                          dplane_op2str(op), ipset->ipset_name,
+                          ipset_entry->unique, ipset_entry->filter_bm);
+       }
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+       dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
+       ctx->zd_is_update = false;
+
+       ctx->zd_vrf_id = ipset->vrf_id;
+
+       memcpy(&ctx->u.ipset_entry.entry, ipset_entry,
+              sizeof(struct zebra_pbr_ipset_entry));
+       ctx->u.ipset_entry.entry.backpointer = NULL;
+       ctx->u.ipset_entry.info.type = ipset->type;
+       memcpy(&ctx->u.ipset_entry.info.ipset_name, &ipset->ipset_name,
+              ZEBRA_IPSET_NAME_SIZE);
+
+       return AOK;
+}
+
+
 /*
  * Enqueue a new update,
  * and ensure an event is active for the dataplane pthread.
@@ -3738,6 +3869,95 @@ dplane_pbr_iptable_delete(struct zebra_pbr_iptable *iptable)
        return iptable_update_internal(DPLANE_OP_IPTABLE_DELETE, iptable);
 }
 
+/*
+ * Common helper api for ipset updates
+ */
+static enum zebra_dplane_result
+ipset_update_internal(enum dplane_op_e op, struct zebra_pbr_ipset *ipset)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       struct zebra_dplane_ctx *ctx;
+       int ret;
+
+       ctx = dplane_ctx_alloc();
+
+       ret = dplane_ctx_ipset_init(ctx, op, ipset);
+       if (ret != AOK)
+               goto done;
+
+       ret = dplane_update_enqueue(ctx);
+
+done:
+       atomic_fetch_add_explicit(&zdplane_info.dg_ipset_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               atomic_fetch_add_explicit(&zdplane_info.dg_ipset_errors, 1,
+                                         memory_order_relaxed);
+               dplane_ctx_free(&ctx);
+       }
+
+       return result;
+}
+
+enum zebra_dplane_result dplane_pbr_ipset_add(struct zebra_pbr_ipset *ipset)
+{
+       return ipset_update_internal(DPLANE_OP_IPSET_ADD, ipset);
+}
+
+enum zebra_dplane_result dplane_pbr_ipset_delete(struct zebra_pbr_ipset *ipset)
+{
+       return ipset_update_internal(DPLANE_OP_IPSET_DELETE, ipset);
+}
+
+/*
+ * Common helper api for ipset updates
+ */
+static enum zebra_dplane_result
+ipset_entry_update_internal(enum dplane_op_e op,
+                           struct zebra_pbr_ipset_entry *ipset_entry)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       struct zebra_dplane_ctx *ctx;
+       int ret;
+
+       ctx = dplane_ctx_alloc();
+
+       ret = dplane_ctx_ipset_entry_init(ctx, op, ipset_entry);
+       if (ret != AOK)
+               goto done;
+
+       ret = dplane_update_enqueue(ctx);
+
+done:
+       atomic_fetch_add_explicit(&zdplane_info.dg_ipset_entry_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               atomic_fetch_add_explicit(&zdplane_info.dg_ipset_entry_errors,
+                                         1, memory_order_relaxed);
+               dplane_ctx_free(&ctx);
+       }
+
+       return result;
+}
+
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_add(struct zebra_pbr_ipset_entry *ipset)
+{
+       return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_ADD, ipset);
+}
+
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset)
+{
+       return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_DELETE, ipset);
+}
+
 /*
  * Handler for 'show dplane'
  */
@@ -3828,6 +4048,18 @@ int dplane_show_helper(struct vty *vty, bool detailed)
                                    memory_order_relaxed);
        vty_out(vty, "IPtable updates:             %" PRIu64 "\n", incoming);
        vty_out(vty, "IPtable errors:              %" PRIu64 "\n", errs);
+       incoming = atomic_load_explicit(&zdplane_info.dg_ipset_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_ipset_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "IPset updates:             %" PRIu64 "\n", incoming);
+       vty_out(vty, "IPset errors:              %" PRIu64 "\n", errs);
+       incoming = atomic_load_explicit(&zdplane_info.dg_ipset_entry_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_ipset_entry_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "IPset entry updates:             %" PRIu64 "\n", incoming);
+       vty_out(vty, "IPset entry errors:              %" PRIu64 "\n", errs);
        return CMD_SUCCESS;
 }
 
@@ -4247,6 +4479,24 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
                        zlog_debug("Dplane iptable update op %s, unique(%u), ctx %p",
                                   dplane_op2str(dplane_ctx_get_op(ctx)), ipt.unique, ctx);
        } break;
+       case DPLANE_OP_IPSET_ADD:
+       case DPLANE_OP_IPSET_DELETE: {
+               struct zebra_pbr_ipset ipset;
+
+               if (dplane_ctx_get_pbr_ipset(ctx, &ipset))
+                       zlog_debug("Dplane ipset update op %s, unique(%u), ctx %p",
+                                  dplane_op2str(dplane_ctx_get_op(ctx)),
+                                  ipset.unique, ctx);
+       } break;
+       case DPLANE_OP_IPSET_ENTRY_ADD:
+       case DPLANE_OP_IPSET_ENTRY_DELETE: {
+               struct zebra_pbr_ipset_entry ipent;
+
+               if (dplane_ctx_get_pbr_ipset_entry(ctx, &ipent))
+                       zlog_debug("Dplane ipset entry update op %s, unique(%u), ctx %p",
+                                  dplane_op2str(dplane_ctx_get_op(ctx)),
+                                  ipent.unique, ctx);
+       } break;
        }
 }
 
@@ -4351,6 +4601,21 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
                                memory_order_relaxed);
                break;
 
+       case DPLANE_OP_IPSET_ADD:
+       case DPLANE_OP_IPSET_DELETE:
+               if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+                       atomic_fetch_add_explicit(&zdplane_info.dg_ipset_errors,
+                                                 1, memory_order_relaxed);
+               break;
+
+       case DPLANE_OP_IPSET_ENTRY_ADD:
+       case DPLANE_OP_IPSET_ENTRY_DELETE:
+               if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+                       atomic_fetch_add_explicit(
+                               &zdplane_info.dg_ipset_entry_errors, 1,
+                               memory_order_relaxed);
+               break;
+
        /* Ignore 'notifications' - no-op */
        case DPLANE_OP_SYS_ROUTE_ADD:
        case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -4374,6 +4639,21 @@ static void kernel_dplane_process_iptable(struct zebra_dplane_provider *prov,
        dplane_provider_enqueue_out_ctx(prov, ctx);
 }
 
+static void kernel_dplane_process_ipset(struct zebra_dplane_provider *prov,
+                                       struct zebra_dplane_ctx *ctx)
+{
+       zebra_pbr_process_ipset(ctx);
+       dplane_provider_enqueue_out_ctx(prov, ctx);
+}
+
+static void
+kernel_dplane_process_ipset_entry(struct zebra_dplane_provider *prov,
+                                 struct zebra_dplane_ctx *ctx)
+{
+       zebra_pbr_process_ipset_entry(ctx);
+       dplane_provider_enqueue_out_ctx(prov, ctx);
+}
+
 /*
  * Kernel provider callback
  */
@@ -4398,9 +4678,16 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
                if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
                        kernel_dplane_log_detail(ctx);
 
-               if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_ADD ||
-                    dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_DELETE))
+               if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_ADD
+                    || dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_DELETE))
                        kernel_dplane_process_iptable(prov, ctx);
+               else if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ADD
+                         || dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_DELETE))
+                       kernel_dplane_process_ipset(prov, ctx);
+               else if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ENTRY_ADD
+                         || dplane_ctx_get_op(ctx)
+                                    == DPLANE_OP_IPSET_ENTRY_DELETE))
+                       kernel_dplane_process_ipset_entry(prov, ctx);
                else
                        TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
        }
index 3416c62b8438a66cc3192902465a9ca91c72da0c..4913ca251f83b548d3c4bdb5592b35fe03fad8af 100644 (file)
@@ -156,9 +156,15 @@ enum dplane_op_e {
        /* bridge port update */
        DPLANE_OP_BR_PORT_UPDATE,
 
-       /* Policy based routing rule update */
+       /* Policy based routing iptable update */
        DPLANE_OP_IPTABLE_ADD,
        DPLANE_OP_IPTABLE_DELETE,
+
+       /* Policy based routing ipset update */
+       DPLANE_OP_IPSET_ADD,
+       DPLANE_OP_IPSET_DELETE,
+       DPLANE_OP_IPSET_ENTRY_ADD,
+       DPLANE_OP_IPSET_ENTRY_DELETE,
 };
 
 /*
@@ -484,6 +490,14 @@ struct zebra_pbr_iptable;
 bool
 dplane_ctx_get_pbr_iptable(const struct zebra_dplane_ctx *ctx,
                           struct zebra_pbr_iptable *table);
+struct zebra_pbr_ipset;
+bool
+dplane_ctx_get_pbr_ipset(const struct zebra_dplane_ctx *ctx,
+                        struct zebra_pbr_ipset *ipset);
+struct zebra_pbr_ipset_entry;
+bool
+dplane_ctx_get_pbr_ipset_entry(const struct zebra_dplane_ctx *ctx,
+                              struct zebra_pbr_ipset_entry *entry);
 /* Accessors for bridge port information */
 uint32_t dplane_ctx_get_br_port_flags(const struct zebra_dplane_ctx *ctx);
 uint32_t
@@ -662,6 +676,18 @@ dplane_pbr_iptable_add(struct zebra_pbr_iptable *iptable);
 enum zebra_dplane_result
 dplane_pbr_iptable_delete(struct zebra_pbr_iptable *iptable);
 
+/* ipset */
+struct zebra_pbr_ipset;
+enum zebra_dplane_result dplane_pbr_ipset_add(struct zebra_pbr_ipset *ipset);
+enum zebra_dplane_result dplane_pbr_ipset_delete(struct zebra_pbr_ipset *ipset);
+
+/* ipset entry */
+struct zebra_pbr_ipset_entry;
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_add(struct zebra_pbr_ipset_entry *ipset);
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset);
+
 /* 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 3fafa19a701c57140a19fb4a4e31caff97021121..3f567d9a7079bda63da21d1c7ed8393ac4a1310c 100644 (file)
@@ -2717,6 +2717,10 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_NONE:
        case DPLANE_OP_IPTABLE_ADD:
        case DPLANE_OP_IPTABLE_DELETE:
+       case DPLANE_OP_IPSET_ADD:
+       case DPLANE_OP_IPSET_DELETE:
+       case DPLANE_OP_IPSET_ENTRY_ADD:
+       case DPLANE_OP_IPSET_ENTRY_DELETE:
                break;
        }
 
index 51c3bd9fdd30e48b5d78e0fe8f4a83334bf9a2a5..92a7a0ba3a5a405902e55849b99184151e22b2ce 100644 (file)
@@ -555,12 +555,56 @@ void zebra_pbr_process_iptable(struct zebra_dplane_ctx *ctx)
        if (dplane_ctx_get_pbr_iptable(ctx, &ipt)) {
                ret = hook_call(zebra_pbr_iptable_update, mode, &ipt);
                if (ret)
-                       dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS);
+                       dplane_ctx_set_status(ctx,
+                                             ZEBRA_DPLANE_REQUEST_SUCCESS);
        }
        if (!ret)
                dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_FAILURE);
 }
 
+void zebra_pbr_process_ipset(struct zebra_dplane_ctx *ctx)
+{
+       int mode, ret = 0;
+       struct zebra_pbr_ipset ipset;
+
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ADD)
+               mode = 1;
+       else
+               mode = 0;
+       if (dplane_ctx_get_pbr_ipset(ctx, &ipset)) {
+               ret = hook_call(zebra_pbr_ipset_update, mode, &ipset);
+               if (ret)
+                       dplane_ctx_set_status(ctx,
+                                             ZEBRA_DPLANE_REQUEST_SUCCESS);
+       }
+       if (!ret)
+               dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_FAILURE);
+}
+
+void zebra_pbr_process_ipset_entry(struct zebra_dplane_ctx *ctx)
+{
+       int mode, ret = 0;
+       struct zebra_pbr_ipset_entry ipset_entry;
+       struct zebra_pbr_ipset ipset;
+
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ENTRY_ADD)
+               mode = 1;
+       else
+               mode = 0;
+
+       if (!dplane_ctx_get_pbr_ipset_entry(ctx, &ipset_entry))
+               return;
+       if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
+               return;
+       ipset_entry.backpointer = &ipset;
+
+       ret = hook_call(zebra_pbr_ipset_entry_update, mode, &ipset_entry);
+       if (ret)
+               dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS);
+       else
+               dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_FAILURE);
+}
+
 static void zebra_pbr_cleanup_rules(struct hash_bucket *b, void *data)
 {
        struct zebra_pbr_rule *rule = b->data;
@@ -651,13 +695,8 @@ static void *pbr_ipset_alloc_intern(void *arg)
 
 void zebra_pbr_create_ipset(struct zebra_pbr_ipset *ipset)
 {
-       int ret;
-
        (void)hash_get(zrouter.ipset_hash, ipset, pbr_ipset_alloc_intern);
-       ret = hook_call(zebra_pbr_ipset_update, 1, ipset);
-       kernel_pbr_ipset_add_del_status(ipset,
-                                       ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
-                                       : ZEBRA_DPLANE_INSTALL_FAILURE);
+       (void)dplane_pbr_ipset_add(ipset);
 }
 
 void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset)
@@ -665,7 +704,7 @@ void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset)
        struct zebra_pbr_ipset *lookup;
 
        lookup = hash_lookup(zrouter.ipset_hash, ipset);
-       hook_call(zebra_pbr_ipset_update, 0, ipset);
+       (void)dplane_pbr_ipset_delete(ipset);
        if (lookup) {
                hash_release(zrouter.ipset_hash, lookup);
                XFREE(MTYPE_TMP, lookup);
@@ -730,14 +769,9 @@ static void *pbr_ipset_entry_alloc_intern(void *arg)
 
 void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
 {
-       int ret;
-
        (void)hash_get(zrouter.ipset_entry_hash, ipset,
                       pbr_ipset_entry_alloc_intern);
-       ret = hook_call(zebra_pbr_ipset_entry_update, 1, ipset);
-       kernel_pbr_ipset_entry_add_del_status(ipset,
-                                       ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
-                                       : ZEBRA_DPLANE_INSTALL_FAILURE);
+       (void)dplane_pbr_ipset_entry_add(ipset);
 }
 
 void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
@@ -745,7 +779,7 @@ void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
        struct zebra_pbr_ipset_entry *lookup;
 
        lookup = hash_lookup(zrouter.ipset_entry_hash, ipset);
-       hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
+       (void)dplane_pbr_ipset_entry_delete(ipset);
        if (lookup) {
                hash_release(zrouter.ipset_entry_hash, lookup);
                XFREE(MTYPE_TMP, lookup);
@@ -836,6 +870,26 @@ void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx)
                                           res == ZEBRA_DPLANE_REQUEST_SUCCESS
                                                ? ZAPI_IPTABLE_REMOVED
                                                : ZAPI_IPTABLE_FAIL_REMOVE);
+       else if (op == DPLANE_OP_IPSET_ADD)
+               zsend_ipset_notify_owner(ctx,
+                                        res == ZEBRA_DPLANE_REQUEST_SUCCESS
+                                                ? ZAPI_IPSET_INSTALLED
+                                                : ZAPI_IPSET_FAIL_INSTALL);
+       else if (op == DPLANE_OP_IPSET_DELETE)
+               zsend_ipset_notify_owner(ctx,
+                                        res == ZEBRA_DPLANE_REQUEST_SUCCESS
+                                                ? ZAPI_IPSET_REMOVED
+                                                : ZAPI_IPSET_FAIL_REMOVE);
+       else if (op == DPLANE_OP_IPSET_ENTRY_ADD)
+               zsend_ipset_entry_notify_owner(
+                       ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
+                                    ? ZAPI_IPSET_ENTRY_INSTALLED
+                                    : ZAPI_IPSET_ENTRY_FAIL_INSTALL);
+       else if (op == DPLANE_OP_IPSET_ENTRY_DELETE)
+               zsend_ipset_entry_notify_owner(
+                       ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
+                                    ? ZAPI_IPSET_ENTRY_REMOVED
+                                    : ZAPI_IPSET_ENTRY_FAIL_REMOVE);
        else
                flog_err(
                        EC_ZEBRA_PBR_RULE_UPDATE,
@@ -846,59 +900,6 @@ void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx)
        dplane_ctx_fini(&ctx);
 }
 
-/*
- * Handle success or failure of ipset (un)install in the kernel.
- */
-void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
-                                   enum zebra_dplane_status res)
-{
-       switch (res) {
-       case ZEBRA_DPLANE_INSTALL_SUCCESS:
-               zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED);
-               break;
-       case ZEBRA_DPLANE_INSTALL_FAILURE:
-               zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
-               break;
-       case ZEBRA_DPLANE_DELETE_SUCCESS:
-               zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
-               break;
-       case ZEBRA_DPLANE_DELETE_FAILURE:
-               zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_REMOVE);
-               break;
-       case ZEBRA_DPLANE_STATUS_NONE:
-               break;
-       }
-}
-
-/*
- * Handle success or failure of ipset (un)install in the kernel.
- */
-void kernel_pbr_ipset_entry_add_del_status(
-                       struct zebra_pbr_ipset_entry *ipset,
-                       enum zebra_dplane_status res)
-{
-       switch (res) {
-       case ZEBRA_DPLANE_INSTALL_SUCCESS:
-               zsend_ipset_entry_notify_owner(ipset,
-                                              ZAPI_IPSET_ENTRY_INSTALLED);
-               break;
-       case ZEBRA_DPLANE_INSTALL_FAILURE:
-               zsend_ipset_entry_notify_owner(ipset,
-                                              ZAPI_IPSET_ENTRY_FAIL_INSTALL);
-               break;
-       case ZEBRA_DPLANE_DELETE_SUCCESS:
-               zsend_ipset_entry_notify_owner(ipset,
-                                              ZAPI_IPSET_ENTRY_REMOVED);
-               break;
-       case ZEBRA_DPLANE_DELETE_FAILURE:
-               zsend_ipset_entry_notify_owner(ipset,
-                                              ZAPI_IPSET_ENTRY_FAIL_REMOVE);
-               break;
-       case ZEBRA_DPLANE_STATUS_NONE:
-               break;
-       }
-}
-
 /*
  * Handle rule delete notification from kernel.
  */
index 1e025bab64f7c48b860a7fdfda7d76f89146a4da..ef930336614b81e22014a8baab1df1584a452f25 100644 (file)
@@ -64,6 +64,15 @@ struct zebra_pbr_rule {
  *
  * This is a filter mapped on ipset entries
  */
+struct zebra_pbr_ipset_info {
+       /* type is encoded as uint32_t
+        * but value is an enum ipset_type
+        */
+       uint32_t type;
+
+       char ipset_name[ZEBRA_IPSET_NAME_SIZE];
+};
+
 struct zebra_pbr_ipset {
        /*
         * Originating zclient sock fd, so we can know who to send
@@ -85,6 +94,7 @@ struct zebra_pbr_ipset {
        char ipset_name[ZEBRA_IPSET_NAME_SIZE];
 };
 
+
 /*
  * An IPSet Entry Filter
  *
@@ -178,6 +188,8 @@ void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset);
 void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable);
 void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable);
 void zebra_pbr_process_iptable(struct zebra_dplane_ctx *ctx);
+void zebra_pbr_process_ipset(struct zebra_dplane_ctx *ctx);
+void zebra_pbr_process_ipset_entry(struct zebra_dplane_ctx *ctx);
 
 /*
  * Get to know existing PBR rules in the kernel - typically called at startup.
index b6303485fabcec338ed4885c5f2ad88132a3dcf4..128edd9fd312ceb2f63a2870915c08771ab4721f 100644 (file)
@@ -3889,6 +3889,10 @@ static int rib_process_dplane_results(struct thread *thread)
                        case DPLANE_OP_RULE_UPDATE:
                        case DPLANE_OP_IPTABLE_ADD:
                        case DPLANE_OP_IPTABLE_DELETE:
+                       case DPLANE_OP_IPSET_ADD:
+                       case DPLANE_OP_IPSET_DELETE:
+                       case DPLANE_OP_IPSET_ENTRY_ADD:
+                       case DPLANE_OP_IPSET_ENTRY_DELETE:
                                zebra_pbr_dplane_result(ctx);
                                break;