diff --git a/lib/log.c b/lib/log.c index f5aff756dd..dbfc95da86 100644 --- a/lib/log.c +++ b/lib/log.c @@ -968,6 +968,10 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_TABLE_MANAGER_CONNECT), DESC_ENTRY(ZEBRA_GET_TABLE_CHUNK), DESC_ENTRY(ZEBRA_RELEASE_TABLE_CHUNK), + DESC_ENTRY(ZEBRA_IPSET_CREATE), + DESC_ENTRY(ZEBRA_IPSET_DESTROY), + DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD), + DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE), }; #undef DESC_ENTRY diff --git a/lib/zclient.h b/lib/zclient.h index a77b1c1f94..3c6e1b3208 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -140,6 +140,10 @@ typedef enum { ZEBRA_TABLE_MANAGER_CONNECT, ZEBRA_GET_TABLE_CHUNK, ZEBRA_RELEASE_TABLE_CHUNK, + ZEBRA_IPSET_CREATE, + ZEBRA_IPSET_DESTROY, + ZEBRA_IPSET_ENTRY_ADD, + ZEBRA_IPSET_ENTRY_DELETE, } zebra_message_types_t; struct redist_proto { diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 1855b54371..cec891b7f3 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -283,6 +283,20 @@ static void *pbr_ipset_alloc_intern(void *arg) return new; } +static struct zebra_pbr_ipset *zpi_found; + +static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg) +{ + struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data; + char *ipset_name = (char *)arg; + + if (!strncmp(ipset_name, zpi->ipset_name, ZEBRA_IPSET_NAME_SIZE)) { + zpi_found = zpi; + return HASHWALK_ABORT; + } + return HASHWALK_CONTINUE; +} + void zebra_pbr_create_ipset(struct zebra_ns *zns, struct zebra_pbr_ipset *ipset) { @@ -309,6 +323,16 @@ void zebra_pbr_destroy_ipset(struct zebra_ns *zns, __PRETTY_FUNCTION__); } +struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns, + char *ipsetname) +{ + if (!ipsetname) + return NULL; + zpi_found = NULL; + hash_walk(zns->ipset_hash, zebra_pbr_ipset_pername_walkcb, ipsetname); + return zpi_found; +} + static void *pbr_ipset_entry_alloc_intern(void *arg) { struct zebra_pbr_ipset_entry *zpi; diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 31e20a3078..2060cc25ec 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -150,6 +150,8 @@ void zebra_pbr_create_ipset(struct zebra_ns *zns, struct zebra_pbr_ipset *ipset); void zebra_pbr_destroy_ipset(struct zebra_ns *zns, struct zebra_pbr_ipset *ipset); +struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns, + char *ipsetname); void zebra_pbr_add_ipset_entry(struct zebra_ns *zns, struct zebra_pbr_ipset_entry *ipset); void zebra_pbr_del_ipset_entry(struct zebra_ns *zns, diff --git a/zebra/zserv.c b/zebra/zserv.c index c06efbfb4b..942e60c798 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2685,7 +2685,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) zpr.ifp = if_lookup_by_index(ifindex, VRF_UNKNOWN); if (!zpr.ifp) { - zlog_debug("FAiled to lookup ifindex: %u", ifindex); + zlog_debug("Failed to lookup ifindex: %u", ifindex); return; } @@ -2711,6 +2711,82 @@ stream_failure: return; } + +static inline void zread_ipset(ZAPI_HANDLER_ARGS) +{ + struct zebra_pbr_ipset zpi; + struct stream *s; + uint32_t total, i; + + s = msg; + STREAM_GETL(s, total); + + for (i = 0; i < total; i++) { + memset(&zpi, 0, sizeof(zpi)); + + zpi.sock = client->sock; + STREAM_GETL(s, zpi.unique); + STREAM_GETL(s, zpi.type); + STREAM_GET(&zpi.ipset_name, s, + ZEBRA_IPSET_NAME_SIZE); + + if (hdr->command == ZEBRA_IPSET_CREATE) + zebra_pbr_create_ipset(zvrf->zns, &zpi); + else + zebra_pbr_destroy_ipset(zvrf->zns, &zpi); + } + +stream_failure: + return; +} + +static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS) +{ + struct zebra_pbr_ipset_entry zpi; + struct zebra_pbr_ipset ipset; + struct stream *s; + uint32_t total, i; + + s = msg; + STREAM_GETL(s, total); + + for (i = 0; i < total; i++) { + memset(&zpi, 0, sizeof(zpi)); + memset(&ipset, 0, sizeof(ipset)); + + zpi.sock = client->sock; + STREAM_GETL(s, zpi.unique); + STREAM_GET(&ipset.ipset_name, s, + ZEBRA_IPSET_NAME_SIZE); + STREAM_GETC(s, zpi.src.family); + STREAM_GETC(s, zpi.src.prefixlen); + STREAM_GET(&zpi.src.u.prefix, s, + prefix_blen(&zpi.src)); + STREAM_GETC(s, zpi.dst.family); + STREAM_GETC(s, zpi.dst.prefixlen); + STREAM_GET(&zpi.dst.u.prefix, s, + prefix_blen(&zpi.dst)); + + if (!is_default_prefix(&zpi.src)) + zpi.filter_bm |= PBR_FILTER_SRC_IP; + + if (!is_default_prefix(&zpi.dst)) + zpi.filter_bm |= PBR_FILTER_DST_IP; + + /* calculate backpointer */ + zpi.backpointer = zebra_pbr_lookup_ipset_pername(zvrf->zns, + ipset.ipset_name); + if (hdr->command == ZEBRA_IPSET_ENTRY_ADD) + zebra_pbr_add_ipset_entry(zvrf->zns, &zpi); + else + zebra_pbr_del_ipset_entry(zvrf->zns, &zpi); + } + +stream_failure: + return; +} + + void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_ROUTER_ID_ADD] = zread_router_id_add, [ZEBRA_ROUTER_ID_DELETE] = zread_router_id_delete, @@ -2771,6 +2847,10 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_TABLE_MANAGER_CONNECT] = zread_table_manager_request, [ZEBRA_GET_TABLE_CHUNK] = zread_table_manager_request, [ZEBRA_RELEASE_TABLE_CHUNK] = zread_table_manager_request, + [ZEBRA_IPSET_CREATE] = zread_ipset, + [ZEBRA_IPSET_DESTROY] = zread_ipset, + [ZEBRA_IPSET_ENTRY_ADD] = zread_ipset_entry, + [ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry, }; static inline void zserv_handle_commands(struct zserv *client,