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:
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);
if (zclient_debug)
zlog_debug("%s: %u", __func__, uni);
*unique = uni;
+ *note = (enum zapi_ipset_entry_notify_owner)notew;
return true;
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;
};
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,
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:
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;
}
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_put(s, ¬e, 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;
}
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, ¬e, 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;
}
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_put(s, ¬e, 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);
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);
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
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 */
_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;
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) {
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);
}
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;
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
*/
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.
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'
*/
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;
}
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;
}
}
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:
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
*/
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);
}
/* 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,
};
/*
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
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);
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;
}
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;
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)
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);
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)
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);
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,
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.
*/
*
* 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
char ipset_name[ZEBRA_IPSET_NAME_SIZE];
};
+
/*
* An IPSet Entry Filter
*
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.
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;