Merge pull request #8124 from pguibert6WIND/ipsec_iptable_dplane

zebra: move netfilter contexts to zebra dplane
This commit is contained in:
Mark Stapp 2021-03-10 16:43:15 -05:00 committed by GitHub
commit 6ff2514b41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 683 additions and 140 deletions

View 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;

View 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,

View File

@ -1350,6 +1350,14 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_BR_PORT_UPDATE:
return FRR_NETLINK_SUCCESS;
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:
return FRR_NETLINK_ERROR;
}

View 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;
}
@ -886,27 +892,32 @@ void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_IPSET_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->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,27 +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(struct zebra_pbr_iptable *iptable,
enum zapi_iptable_notify_owner 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_ipset_entry ipent;
struct zebra_pbr_ipset ipset;
uint16_t cmd = ZEBRA_IPSET_ENTRY_NOTIFY_OWNER;
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 %u", __func__, iptable->unique);
zlog_debug("%s: Notifying %s id %u note %u", __func__,
zserv_command_string(cmd), ipent.unique, note);
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
if (iptable->sock == client->sock)
if (ipent.sock == client->sock)
break;
}
@ -944,9 +964,10 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_IPTABLE_NOTIFY_OWNER, VRF_DEFAULT);
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_put(s, &note, sizeof(note));
stream_putl(s, iptable->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);

View 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(struct zebra_pbr_iptable *iptable,
enum zapi_iptable_notify_owner note);
extern void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
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);

View File

@ -42,6 +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_NETFILTER, "Zebra Netfilter Internal Object")
#ifndef AOK
# define AOK 0
@ -307,6 +308,12 @@ struct zebra_dplane_ctx {
struct dplane_mac_info macinfo;
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 */
@ -438,6 +445,14 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_update_yields;
_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;
@ -656,7 +671,29 @@ 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) {
struct listnode *node, *nnode;
char *ifname;
for (ALL_LIST_ELEMENTS(
ctx->u.iptable.interface_name_list, node,
nnode, ifname)) {
LISTNODE_DETACH(
ctx->u.iptable.interface_name_list,
node);
XFREE(MTYPE_DP_NETFILTER, ifname);
}
list_delete(&ctx->u.iptable.interface_name_list);
}
}
}
@ -895,6 +932,25 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_NEIGH_DISCOVER:
ret = "NEIGH_DISCOVER";
break;
case DPLANE_OP_IPTABLE_ADD:
ret = "IPTABLE_ADD";
break;
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;
@ -1843,6 +1899,46 @@ dplane_ctx_get_br_port_backup_nhg_id(const struct zebra_dplane_ctx *ctx)
return ctx->u.br_port.backup_nhg_id;
}
/* Accessors for PBR iptable information */
bool
dplane_ctx_get_pbr_iptable(const struct zebra_dplane_ctx *ctx,
struct zebra_pbr_iptable *table)
{
DPLANE_CTX_VALID(ctx);
memcpy(table, &ctx->u.iptable, sizeof(struct zebra_pbr_iptable));
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
*/
@ -2398,6 +2494,126 @@ static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx,
return AOK;
}
/**
* dplane_ctx_iptable_init() - Initialize a context block for a PBR iptable
* update.
*
* @ctx: Dataplane context to init
* @op: Operation being performed
* @new_rule: PBR iptable
*
* Return: Result status
*/
static int dplane_ctx_iptable_init(struct zebra_dplane_ctx *ctx,
enum dplane_op_e op,
struct zebra_pbr_iptable *iptable)
{
char *ifname;
struct listnode *node;
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
zlog_debug(
"init dplane ctx %s: Unique %u Fwmark %u Family %s Action %s",
dplane_op2str(op), iptable->unique, iptable->fwmark,
family2str(iptable->family),
iptable->action == ZEBRA_IPTABLES_DROP ? "Drop"
: "Forward");
}
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 = iptable->vrf_id;
memcpy(&ctx->u.iptable, iptable, sizeof(struct zebra_pbr_iptable));
ctx->u.iptable.interface_name_list = NULL;
if (iptable->nb_interface > 0) {
ctx->u.iptable.interface_name_list = list_new();
for (ALL_LIST_ELEMENTS_RO(iptable->interface_name_list, node,
ifname)) {
listnode_add(ctx->u.iptable.interface_name_list,
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.
@ -3608,6 +3824,139 @@ enum zebra_dplane_result dplane_pbr_rule_update(struct zebra_pbr_rule *old_rule,
{
return rule_update_internal(DPLANE_OP_RULE_UPDATE, new_rule, old_rule);
}
/*
* Common helper api for iptable updates
*/
static enum zebra_dplane_result
iptable_update_internal(enum dplane_op_e op, struct zebra_pbr_iptable *iptable)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
struct zebra_dplane_ctx *ctx;
int ret;
ctx = dplane_ctx_alloc();
ret = dplane_ctx_iptable_init(ctx, op, iptable);
if (ret != AOK)
goto done;
ret = dplane_update_enqueue(ctx);
done:
atomic_fetch_add_explicit(&zdplane_info.dg_iptable_in, 1,
memory_order_relaxed);
if (ret == AOK)
result = ZEBRA_DPLANE_REQUEST_QUEUED;
else {
atomic_fetch_add_explicit(&zdplane_info.dg_iptable_errors, 1,
memory_order_relaxed);
dplane_ctx_free(&ctx);
}
return result;
}
enum zebra_dplane_result
dplane_pbr_iptable_add(struct zebra_pbr_iptable *iptable)
{
return iptable_update_internal(DPLANE_OP_IPTABLE_ADD, iptable);
}
enum zebra_dplane_result
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'
@ -3693,6 +4042,24 @@ int dplane_show_helper(struct vty *vty, bool detailed)
vty_out(vty, "Bridge port updates: %" PRIu64 "\n", incoming);
vty_out(vty, "Bridge port errors: %" PRIu64 "\n", errs);
incoming = atomic_load_explicit(&zdplane_info.dg_iptable_in,
memory_order_relaxed);
errs = atomic_load_explicit(&zdplane_info.dg_iptable_errors,
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;
}
@ -4103,6 +4470,33 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NONE:
break;
case DPLANE_OP_IPTABLE_ADD:
case DPLANE_OP_IPTABLE_DELETE: {
struct zebra_pbr_iptable ipt;
if (dplane_ctx_get_pbr_iptable(ctx, &ipt))
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;
}
}
@ -4199,6 +4593,29 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
1, memory_order_relaxed);
break;
case DPLANE_OP_IPTABLE_ADD:
case DPLANE_OP_IPTABLE_DELETE:
if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
atomic_fetch_add_explicit(
&zdplane_info.dg_iptable_errors, 1,
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:
@ -4215,6 +4632,28 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
}
}
static void kernel_dplane_process_iptable(struct zebra_dplane_provider *prov,
struct zebra_dplane_ctx *ctx)
{
zebra_pbr_process_iptable(ctx);
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
*/
@ -4236,11 +4675,21 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
ctx = dplane_provider_dequeue_in_ctx(prov);
if (ctx == NULL)
break;
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
kernel_dplane_log_detail(ctx);
TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
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);
}
kernel_update_multi(&work_list);

View File

@ -155,6 +155,16 @@ enum dplane_op_e {
/* bridge port update */
DPLANE_OP_BR_PORT_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,
};
/*
@ -475,7 +485,19 @@ const struct prefix *
dplane_ctx_rule_get_dst_ip(const struct zebra_dplane_ctx *ctx);
const struct prefix *
dplane_ctx_rule_get_old_dst_ip(const struct zebra_dplane_ctx *ctx);
/* Accessors for policy based routing iptable information */
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
@ -648,6 +670,23 @@ 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);
/* iptable */
enum zebra_dplane_result
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,

View File

@ -2715,6 +2715,12 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_BR_PORT_UPDATE:
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;
}

View File

@ -542,6 +542,69 @@ void zebra_pbr_del_rule(struct zebra_pbr_rule *rule)
__func__);
}
void zebra_pbr_process_iptable(struct zebra_dplane_ctx *ctx)
{
int mode, ret = 0;
struct zebra_pbr_iptable ipt;
if (dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_ADD)
mode = 1;
else
mode = 0;
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);
}
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;
@ -632,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)
@ -646,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);
@ -711,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)
@ -726,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);
@ -761,13 +814,8 @@ static void *pbr_iptable_alloc_intern(void *arg)
void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable)
{
int ret;
(void)hash_get(zrouter.iptable_hash, iptable, pbr_iptable_alloc_intern);
ret = hook_call(zebra_pbr_iptable_update, 1, iptable);
kernel_pbr_iptable_add_del_status(iptable,
ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
: ZEBRA_DPLANE_INSTALL_FAILURE);
(void)dplane_pbr_iptable_add(iptable);
}
void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
@ -775,7 +823,7 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
struct zebra_pbr_iptable *lookup;
lookup = hash_lookup(zrouter.iptable_hash, iptable);
hook_call(zebra_pbr_iptable_update, 0, iptable);
(void)dplane_pbr_iptable_delete(iptable);
if (lookup) {
struct listnode *node, *nnode;
char *name;
@ -812,6 +860,36 @@ void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx)
zsend_rule_notify_owner(ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
? ZAPI_RULE_REMOVED
: ZAPI_RULE_FAIL_REMOVE);
else if (op == DPLANE_OP_IPTABLE_ADD)
zsend_iptable_notify_owner(ctx,
res == ZEBRA_DPLANE_REQUEST_SUCCESS
? ZAPI_IPTABLE_INSTALLED
: ZAPI_IPTABLE_FAIL_INSTALL);
else if (op == DPLANE_OP_IPTABLE_DELETE)
zsend_iptable_notify_owner(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,
@ -822,85 +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 success or failure of ipset (un)install in the kernel.
*/
void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
enum zebra_dplane_status res)
{
switch (res) {
case ZEBRA_DPLANE_INSTALL_SUCCESS:
zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED);
break;
case ZEBRA_DPLANE_INSTALL_FAILURE:
zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
break;
case ZEBRA_DPLANE_DELETE_SUCCESS:
zsend_iptable_notify_owner(iptable,
ZAPI_IPTABLE_REMOVED);
break;
case ZEBRA_DPLANE_DELETE_FAILURE:
zsend_iptable_notify_owner(iptable,
ZAPI_IPTABLE_FAIL_REMOVE);
break;
case ZEBRA_DPLANE_STATUS_NONE:
break;
}
}
/*
* Handle rule delete notification from kernel.
*/

View 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
*
@ -177,6 +187,9 @@ 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.
@ -198,9 +211,6 @@ extern void kernel_pbr_ipset_entry_add_del_status(
struct zebra_pbr_ipset_entry *ipset,
enum zebra_dplane_status res);
extern void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
enum zebra_dplane_status res);
/*
* Handle rule delete notification from kernel.
*/

View File

@ -3887,6 +3887,12 @@ static int rib_process_dplane_results(struct thread *thread)
case DPLANE_OP_RULE_ADD:
case DPLANE_OP_RULE_DELETE:
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;