diff options
Diffstat (limited to 'zebra/zapi_msg.c')
| -rw-r--r-- | zebra/zapi_msg.c | 335 |
1 files changed, 299 insertions, 36 deletions
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index dc7c595d26..285f28ccec 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -51,6 +51,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/zebra_mroute.h" #include "zebra/zebra_vxlan.h" +#include "zebra/zebra_evpn_mh.h" #include "zebra/rt.h" #include "zebra/zebra_pbr.h" #include "zebra/table_manager.h" @@ -59,6 +60,7 @@ #include "zebra/zebra_mlag.h" #include "zebra/connected.h" #include "zebra/zebra_opaque.h" +#include "zebra/zebra_srte.h" /* Encoding helpers -------------------------------------------------------- */ @@ -729,9 +731,10 @@ static int route_notify_internal(const struct prefix *p, int type, char buff[PREFIX_STRLEN]; zlog_debug( - "Not Notifying Owner: %u about prefix %s(%u) %d vrf: %u", - type, prefix2str(p, buff, sizeof(buff)), - table_id, note, vrf_id); + "Not Notifying Owner: %s about prefix %s(%u) %d vrf: %u", + zebra_route_string(type), + prefix2str(p, buff, sizeof(buff)), table_id, + note, vrf_id); } return 0; } @@ -739,9 +742,10 @@ static int route_notify_internal(const struct prefix *p, int type, if (IS_ZEBRA_DEBUG_PACKET) { char buff[PREFIX_STRLEN]; - zlog_debug("Notifying Owner: %u about prefix %s(%u) %d vrf: %u", - type, prefix2str(p, buff, sizeof(buff)), - table_id, note, vrf_id); + zlog_debug("Notifying Owner: %s about prefix %s(%u) %d vrf: %u", + zebra_route_string(type), + prefix2str(p, buff, sizeof(buff)), table_id, note, + vrf_id); } s = stream_new(ZEBRA_MAX_PACKET_SIZ); @@ -904,17 +908,18 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable, zserv_send_message(client, s); } -/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ -int zsend_router_id_update(struct zserv *client, struct prefix *p, +/* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */ +int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p, vrf_id_t vrf_id) { int blen; + struct stream *s; /* Check this client need interface information. */ - if (!vrf_bitmap_check(client->ridinfo, vrf_id)) + if (!vrf_bitmap_check(client->ridinfo[afi], vrf_id)) return 0; - struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); /* Message type. */ zclient_create_header(s, ZEBRA_ROUTER_ID_UPDATE, vrf_id); @@ -1073,7 +1078,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) s = msg; - client->nh_reg_time = monotime(NULL); + if (!client->nh_reg_time) + client->nh_reg_time = monotime(NULL); while (l < hdr->length) { STREAM_GETC(s, flags); @@ -1416,6 +1422,7 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, struct nexthop *nexthop = NULL; struct ipaddr vtep_ip; struct interface *ifp; + int i; char nhbuf[INET6_ADDRSTRLEN] = ""; switch (api_nh->type) { @@ -1521,17 +1528,36 @@ static struct nexthop *nexthop_from_zapi(struct route_entry *re, nexthop->weight = api_nh->weight; if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { - if (api_nh->backup_idx < api->backup_nexthop_num) { - /* Capture backup info */ - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); - nexthop->backup_idx = api_nh->backup_idx; - } else { - /* Warn about invalid backup index */ + /* Validate count */ + if (api_nh->backup_num > NEXTHOP_MAX_BACKUPS) { if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: invalid backup nh idx %d", - __func__, api_nh->backup_idx); + zlog_debug("%s: invalid backup nh count %d", + __func__, api_nh->backup_num); + nexthop_free(nexthop); + nexthop = NULL; + goto done; + } + + /* Copy backup info */ + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); + nexthop->backup_num = api_nh->backup_num; + + for (i = 0; i < api_nh->backup_num; i++) { + /* Validate backup index */ + if (api_nh->backup_idx[i] < api->backup_nexthop_num) { + nexthop->backup_idx[i] = api_nh->backup_idx[i]; + } else { + if (IS_ZEBRA_DEBUG_RECV || IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: invalid backup nh idx %d", + __func__, + api_nh->backup_idx[i]); + nexthop_free(nexthop); + nexthop = NULL; + goto done; + } } } + done: return nexthop; } @@ -1627,6 +1653,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) return; } + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE); + nexthop->srte_color = api_nh->srte_color; + } + /* MPLS labels for BGP-LU or Segment Routing */ if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) && api_nh->type != NEXTHOP_TYPE_IFINDEX @@ -1703,7 +1734,12 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) __func__, nhbuf); } UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP); - nexthop->backup_idx = 0; + nexthop->backup_num = 0; + } + + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE); + nexthop->srte_color = api_nh->srte_color; } /* MPLS labels for BGP-LU or Segment Routing */ @@ -1874,20 +1910,48 @@ stream_failure: /* Register zebra server router-id information. Send current router-id */ static void zread_router_id_add(ZAPI_HANDLER_ARGS) { + afi_t afi; + struct prefix p; + STREAM_GETW(msg, afi); + + if (afi <= AFI_UNSPEC || afi >= AFI_MAX) { + zlog_warn( + "Invalid AFI %u while registering for router ID notifications", + afi); + goto stream_failure; + } + /* Router-id information is needed. */ - vrf_bitmap_set(client->ridinfo, zvrf_id(zvrf)); + vrf_bitmap_set(client->ridinfo[afi], zvrf_id(zvrf)); + + router_id_get(afi, &p, zvrf); - router_id_get(&p, zvrf_id(zvrf)); + zsend_router_id_update(client, afi, &p, zvrf_id(zvrf)); - zsend_router_id_update(client, &p, zvrf_id(zvrf)); +stream_failure: + return; } /* Unregister zebra server router-id information. */ static void zread_router_id_delete(ZAPI_HANDLER_ARGS) { - vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); + afi_t afi; + + STREAM_GETW(msg, afi); + + if (afi <= AFI_UNSPEC || afi >= AFI_MAX) { + zlog_warn( + "Invalid AFI %u while unregistering from router ID notifications", + afi); + goto stream_failure; + } + + vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf)); + +stream_failure: + return; } static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf) @@ -1976,8 +2040,58 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS) for (i = 0; i < ZEBRA_ROUTE_MAX; i++) vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf)); vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf)); + vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf)); + } +} + +/* + * Validate incoming zapi mpls lsp / labels message + */ +static int zapi_labels_validate(const struct zapi_labels *zl) +{ + int ret = -1; + int i, j, idx; + uint32_t bits[8]; + uint32_t ival; + const struct zapi_nexthop *znh; + + /* Validate backup info: no duplicates for a single primary */ + if (zl->backup_nexthop_num == 0) { + ret = 0; + goto done; + } + + for (j = 0; j < zl->nexthop_num; j++) { + znh = &zl->nexthops[j]; + + memset(bits, 0, sizeof(bits)); + + for (i = 0; i < znh->backup_num; i++) { + idx = znh->backup_idx[i] / 32; + + ival = 1 << znh->backup_idx[i] % 32; + + /* Check whether value is already used */ + if (ival & bits[idx]) { + /* Fail */ + + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: invalid zapi mpls message: duplicate backup nexthop index %d", + __func__, + znh->backup_idx[i]); + goto done; + } + + /* Mark index value */ + bits[idx] |= ival; + } } - vrf_bitmap_unset(client->ridinfo, zvrf_id(zvrf)); + + ret = 0; + +done: + + return ret; } /* @@ -2006,6 +2120,10 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS) if (!mpls_enabled) return; + /* Validate; will debug on failure */ + if (zapi_labels_validate(&zl) < 0) + return; + ret = mpls_zapi_labels_process(true, zvrf, &zl); if (ret < 0) { if (IS_ZEBRA_DEBUG_RECV) @@ -2087,6 +2205,10 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS) if (!mpls_enabled) return; + /* Validate; will debug on failure */ + if (zapi_labels_validate(&zl) < 0) + return; + /* This removes everything, then re-adds from the client's * zapi message. Since the LSP will be processed later, on this * this same pthread, all of the changes will 'appear' at once. @@ -2099,6 +2221,107 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS) mpls_zapi_labels_process(true, zvrf, &zl); } +static void zread_sr_policy_set(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_sr_policy zp; + struct zapi_srte_tunnel *zt; + struct zebra_sr_policy *policy; + + /* Get input stream. */ + s = msg; + if (zapi_sr_policy_decode(s, &zp) < 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to decode zapi_sr_policy sent", + __PRETTY_FUNCTION__); + return; + } + zt = &zp.segment_list; + if (zt->label_num < 1) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug( + "%s: SR-TE tunnel must contain at least one label", + __PRETTY_FUNCTION__); + return; + } + + if (!mpls_enabled) + return; + + policy = zebra_sr_policy_find(zp.color, &zp.endpoint); + if (!policy) + policy = zebra_sr_policy_add(zp.color, &zp.endpoint, zp.name); + /* TODO: per-VRF list of SR-TE policies. */ + policy->zvrf = zvrf; + + zebra_sr_policy_validate(policy, &zp.segment_list); +} + +static void zread_sr_policy_delete(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + struct zapi_sr_policy zp; + struct zebra_sr_policy *policy; + + /* Get input stream. */ + s = msg; + if (zapi_sr_policy_decode(s, &zp) < 0) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to decode zapi_sr_policy sent", + __PRETTY_FUNCTION__); + return; + } + + if (!mpls_enabled) + return; + + policy = zebra_sr_policy_find(zp.color, &zp.endpoint); + if (!policy) { + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("%s: Unable to find SR-TE policy", + __PRETTY_FUNCTION__); + return; + } + + zebra_sr_policy_del(policy); +} + +int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint, + char *name, int status) +{ + struct zserv *client; + struct stream *s; + + client = zserv_find_client(ZEBRA_ROUTE_SRTE, 0); + if (!client) { + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug( + "Not notifying pathd about policy %s" + " status change to %d", + name, status); + return 0; + } + + if (IS_ZEBRA_DEBUG_PACKET) + zlog_debug( + "Notifying pathd about policy %s status change" + " to %d", + name, status); + + s = stream_new(ZEBRA_MAX_PACKET_SIZ); + stream_reset(s); + + zclient_create_header(s, ZEBRA_SR_POLICY_NOTIFY_STATUS, VRF_DEFAULT); + stream_putl(s, color); + stream_put_ipaddr(s, endpoint); + stream_write(s, name, SRTE_POLICY_NAME_MAX_LENGTH); + stream_putl(s, status); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zserv_send_message(client, s); +} + /* Send response to a table manager connect request to client */ static void zread_table_manager_connect(struct zserv *client, struct stream *msg, vrf_id_t vrf_id) @@ -2526,6 +2749,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) STREAM_GET(&zpr.rule.filter.dst_ip.u.prefix, s, prefix_blen(&zpr.rule.filter.dst_ip)); STREAM_GETW(s, zpr.rule.filter.dst_port); + STREAM_GETC(s, zpr.rule.filter.dsfield); STREAM_GETL(s, zpr.rule.filter.fwmark); STREAM_GETL(s, zpr.rule.action.table); STREAM_GETL(s, zpr.rule.ifindex); @@ -2556,14 +2780,16 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) if (zpr.rule.filter.dst_port) zpr.rule.filter.filter_bm |= PBR_FILTER_DST_PORT; + if (zpr.rule.filter.dsfield) + zpr.rule.filter.filter_bm |= PBR_FILTER_DSFIELD; + if (zpr.rule.filter.fwmark) zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK; if (!(zpr.rule.filter.src_ip.family == AF_INET || zpr.rule.filter.src_ip.family == AF_INET6)) { zlog_warn( - "Unsupported PBR source IP family: %s (%" PRIu8 - ")", + "Unsupported PBR source IP family: %s (%hhu)", family2str(zpr.rule.filter.src_ip.family), zpr.rule.filter.src_ip.family); return; @@ -2571,8 +2797,7 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) if (!(zpr.rule.filter.dst_ip.family == AF_INET || zpr.rule.filter.dst_ip.family == AF_INET6)) { zlog_warn( - "Unsupported PBR destination IP family: %s (%" PRIu8 - ")", + "Unsupported PBR destination IP family: %s (%hhu)", family2str(zpr.rule.filter.dst_ip.family), zpr.rule.filter.dst_ip.family); return; @@ -2667,16 +2892,14 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS) if (!(zpi.dst.family == AF_INET || zpi.dst.family == AF_INET6)) { zlog_warn( - "Unsupported PBR destination IP family: %s (%" PRIu8 - ")", + "Unsupported PBR destination IP family: %s (%hhu)", family2str(zpi.dst.family), zpi.dst.family); goto stream_failure; } if (!(zpi.src.family == AF_INET || zpi.src.family == AF_INET6)) { zlog_warn( - "Unsupported PBR source IP family: %s (%" PRIu8 - ")", + "Unsupported PBR source IP family: %s (%hhu)", family2str(zpi.src.family), zpi.src.family); goto stream_failure; } @@ -2739,6 +2962,41 @@ stream_failure: return; } +static inline void zread_neigh_discover(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + ifindex_t ifindex; + struct interface *ifp; + struct prefix p; + struct ipaddr ip; + + s = msg; + + STREAM_GETL(s, ifindex); + + ifp = if_lookup_by_index_per_ns(zvrf->zns, ifindex); + if (!ifp) { + zlog_debug("Failed to lookup ifindex: %u", ifindex); + return; + } + + STREAM_GETC(s, p.family); + STREAM_GETC(s, p.prefixlen); + STREAM_GET(&p.u.prefix, s, prefix_blen(&p)); + + if (p.family == AF_INET) + SET_IPADDR_V4(&ip); + else + SET_IPADDR_V6(&ip); + + memcpy(&ip.ip.addr, &p.u.prefix, prefix_blen(&p)); + + dplane_neigh_discover(ifp, &ip); + +stream_failure: + return; +} + static void zsend_error_msg(struct zserv *client, enum zebra_error_types error, struct zmsghdr *bad_hdr) { @@ -2798,6 +3056,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register, [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable, [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable, + [ZEBRA_SR_POLICY_SET] = zread_sr_policy_set, + [ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete, [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add, [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete, [ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace, @@ -2812,6 +3072,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_ADVERTISE_SVI_MACIP] = zebra_vxlan_advertise_svi_macip, [ZEBRA_ADVERTISE_SUBNET] = zebra_vxlan_advertise_subnet, [ZEBRA_ADVERTISE_ALL_VNI] = zebra_vxlan_advertise_all_vni, + [ZEBRA_REMOTE_ES_VTEP_ADD] = zebra_evpn_proc_remote_es, + [ZEBRA_REMOTE_ES_VTEP_DEL] = zebra_evpn_proc_remote_es, [ZEBRA_REMOTE_VTEP_ADD] = zebra_vxlan_remote_vtep_add, [ZEBRA_REMOTE_VTEP_DEL] = zebra_vxlan_remote_vtep_del, [ZEBRA_REMOTE_MACIP_ADD] = zebra_vxlan_remote_macip_add, @@ -2838,8 +3100,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register, [ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister, [ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg, - [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities -}; + [ZEBRA_CLIENT_CAPABILITIES] = zread_client_capabilities, + [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover}; #if defined(HANDLE_ZAPI_FUZZING) extern struct zebra_privs_t zserv_privs; @@ -2890,7 +3152,8 @@ void zserv_handle_commands(struct zserv *client, struct stream_fifo *fifo) zapi_parse_header(msg, &hdr); - if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) + if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV + && IS_ZEBRA_DEBUG_DETAIL) zserv_log_message(NULL, msg, &hdr); #if defined(HANDLE_ZAPI_FUZZING) |
