diff options
| -rw-r--r-- | bgpd/bgp_flowspec.h | 8 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_util.c | 27 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_util.h | 8 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_vty.c | 68 | ||||
| -rw-r--r-- | bgpd/bgp_keepalives.c | 6 | ||||
| -rw-r--r-- | bgpd/bgp_pbr.c | 231 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 44 | ||||
| -rw-r--r-- | bgpd/bgp_route.h | 2 | ||||
| -rw-r--r-- | bgpd/bgp_table.h | 4 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp_adv.c | 68 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 22 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 140 | ||||
| -rw-r--r-- | doc/user/rpki.rst | 54 | ||||
| -rw-r--r-- | doc/user/zebra.rst | 7 | ||||
| -rw-r--r-- | lib/if.c | 4 | ||||
| -rw-r--r-- | lib/table.h | 8 | ||||
| -rw-r--r-- | lib/vrf.h | 13 | ||||
| -rw-r--r-- | pimd/pim_msg.c | 2 | ||||
| -rw-r--r-- | tests/bgpd/test_bgp_table.c | 4 | ||||
| -rw-r--r-- | tests/bgpd/test_capability.c | 1 | ||||
| -rw-r--r-- | tests/lib/test_srcdest_table.c | 3 | ||||
| -rw-r--r-- | zebra/interface.c | 6 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 2 | ||||
| -rw-r--r-- | zebra/router-id.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_pbr.c | 41 | ||||
| -rw-r--r-- | zebra/zebra_pbr.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 30 | ||||
| -rw-r--r-- | zebra/zebra_vxlan.c | 1 |
28 files changed, 451 insertions, 359 deletions
diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h index 5dd2c3931a..9f69dbedda 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -50,4 +50,12 @@ extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p, extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); +extern int bgp_flowspec_display_match_per_ip(afi_t afi, + struct bgp_table *rib, + struct prefix *match, + int prefix_check, + struct vty *vty, + uint8_t use_json, + json_object *json_paths); + #endif /* _FRR_BGP_FLOWSPEC_H */ diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 1b87427661..6408337a5f 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -73,9 +73,9 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len, return ret; } -static bool bgp_flowspec_contains_prefix(struct prefix *pfs, - struct prefix *input, - int prefix_check) +bool bgp_flowspec_contains_prefix(struct prefix *pfs, + struct prefix *input, + int prefix_check) { uint32_t offset = 0; int type; @@ -564,24 +564,3 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, } return error; } - - -struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi, - struct bgp_table *rib, - struct prefix *match, - int prefix_check) -{ - struct bgp_node *rn; - struct prefix *prefix; - - for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) { - prefix = &rn->p; - - if (prefix->family != AF_FLOWSPEC) - continue; - - if (bgp_flowspec_contains_prefix(prefix, match, prefix_check)) - return rn; - } - return NULL; -} diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h index 2d16e57a36..9bf05847d3 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -50,8 +50,8 @@ struct bgp_pbr_entry_main; extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, struct bgp_pbr_entry_main *bpem); -extern struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi, - struct bgp_table *rib, - struct prefix *match, - int prefix_check); +extern bool bgp_flowspec_contains_prefix(struct prefix *pfs, + struct prefix *input, + int prefix_check); + #endif /* _FRR_BGP_FLOWSPEC_UTIL_H */ diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index c695e7f125..ace888c78d 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -332,16 +332,32 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, struct bgp_info_extra *extra = bgp_info_extra_get(binfo); if (extra->bgp_fs_pbr) { + struct listnode *node; struct bgp_pbr_match_entry *bpme; struct bgp_pbr_match *bpm; + int unit = 0; + struct list *list_bpm; - bpme = (struct bgp_pbr_match_entry *)extra->bgp_fs_pbr; - bpm = bpme->backpointer; - vty_out(vty, "\tinstalled in PBR"); - if (bpm) - vty_out(vty, " (%s)\n", bpm->ipset_name); - else - vty_out(vty, "\n"); + list_bpm = list_new(); + if (listcount(extra->bgp_fs_pbr)) + vty_out(vty, "\tinstalled in PBR"); + for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_pbr, + node, bpme)) { + bpm = bpme->backpointer; + if (listnode_lookup(list_bpm, bpm)) + continue; + listnode_add(list_bpm, bpm); + if (unit == 0) + vty_out(vty, " ("); + else + vty_out(vty, ", "); + vty_out(vty, "%s", bpm->ipset_name); + unit++; + } + if (unit) + vty_out(vty, ")"); + vty_out(vty, "\n"); + list_delete_all_node(list_bpm); } else vty_out(vty, "\tnot installed in PBR\n"); } @@ -444,8 +460,6 @@ int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, RB_FOREACH (pbr_if, bgp_pbr_interface_head, head) { vty_out(vty, " local-install %s\n", pbr_if->name); } - if (!bgp_pbr_interface_any) - vty_out(vty, " no local-install any\n"); return declare_node ? 1 : 0; } @@ -513,17 +527,34 @@ DEFUN (bgp_fs_local_install_ifname, return bgp_fs_local_install_interface(bgp, no, ifname); } -DEFUN (bgp_fs_local_install_any, - bgp_fs_local_install_any_cmd, - "[no] local-install any", - NO_STR - "Apply local policy routing\n" - "Any Interface\n") +extern int bgp_flowspec_display_match_per_ip(afi_t afi, + struct bgp_table *rib, + struct prefix *match, + int prefix_check, + struct vty *vty, + uint8_t use_json, + json_object *json_paths) { - struct bgp *bgp = VTY_GET_CONTEXT(bgp); - const char *no = strmatch(argv[0]->text, (char *)"no") ? "no" : NULL; + struct bgp_node *rn; + struct prefix *prefix; + int display = 0; - return bgp_fs_local_install_interface(bgp, no, NULL); + for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) { + prefix = &rn->p; + + if (prefix->family != AF_FLOWSPEC) + continue; + + if (bgp_flowspec_contains_prefix(prefix, match, prefix_check)) { + route_vty_out_flowspec(vty, &rn->p, + rn->info, use_json ? + NLRI_STRING_FORMAT_JSON : + NLRI_STRING_FORMAT_LARGE, + json_paths); + display++; + } + } + return display; } void bgp_flowspec_vty_init(void) @@ -532,6 +563,5 @@ void bgp_flowspec_vty_init(void) install_element(CONFIG_NODE, &debug_bgp_flowspec_cmd); install_element(ENABLE_NODE, &no_debug_bgp_flowspec_cmd); install_element(CONFIG_NODE, &no_debug_bgp_flowspec_cmd); - install_element(BGP_FLOWSPECV4_NODE, &bgp_fs_local_install_any_cmd); install_element(BGP_FLOWSPECV4_NODE, &bgp_fs_local_install_ifname_cmd); } diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index 1504893c47..3216683a54 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -180,6 +180,12 @@ void *bgp_keepalives_start(void *arg) pthread_cond_init(peerhash_cond, &attrs); pthread_condattr_destroy(&attrs); +#ifdef GNU_LINUX + pthread_setname_np(fpt->thread, "bgpd_ka"); +#elif defined(OPEN_BSD) + pthread_set_name_np(fpt->thread, "bgpd_ka"); +#endif + /* initialize peer hashtable */ peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL); pthread_mutex_lock(peerhash_mtx); diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index b5ddfd4b21..de475d2dcd 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -231,6 +231,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct nexthop *nh, float *rate); +static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add); + static bool bgp_pbr_extract_enumerate_unary_opposite( uint8_t unary_operator, struct bgp_pbr_val_mask *and_valmask, @@ -833,12 +835,12 @@ uint32_t bgp_pbr_match_hash_key(void *arg) key = jhash_1word(pbm->vrf_id, 0x4312abde); key = jhash_1word(pbm->flags, key); - key = jhash_1word(pbm->pkt_len_min, key); - key = jhash_1word(pbm->pkt_len_max, key); - key = jhash_1word(pbm->tcp_flags, key); - key = jhash_1word(pbm->tcp_mask_flags, key); - key = jhash_1word(pbm->dscp_value, key); - key = jhash_1word(pbm->fragment, key); + key = jhash(&pbm->pkt_len_min, 2, key); + key = jhash(&pbm->pkt_len_max, 2, key); + key = jhash(&pbm->tcp_flags, 2, key); + key = jhash(&pbm->tcp_mask_flags, 2, key); + key = jhash(&pbm->dscp_value, 1, key); + key = jhash(&pbm->fragment, 1, key); return jhash_1word(pbm->type, key); } @@ -1225,7 +1227,8 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa, /* unlink bgp_info to bpme */ bgp_info = (struct bgp_info *)bpme->bgp_info; extra = bgp_info_extra_get(bgp_info); - extra->bgp_fs_pbr = NULL; + if (extra->bgp_fs_pbr) + listnode_delete(extra->bgp_fs_pbr, bpme); bpme->bgp_info = NULL; } } @@ -1282,7 +1285,13 @@ static int bgp_pbr_get_remaining_entry(struct hash_backet *backet, void *arg) bpm_temp = bpme->backpointer; if (bpm_temp->vrf_id != bpm->vrf_id || bpm_temp->type != bpm->type || - bpm_temp->flags != bpm->flags) + bpm_temp->flags != bpm->flags || + bpm_temp->tcp_flags != bpm->tcp_flags || + bpm_temp->tcp_mask_flags != bpm->tcp_mask_flags || + bpm_temp->pkt_len_min != bpm->pkt_len_min || + bpm_temp->pkt_len_max != bpm->pkt_len_max || + bpm_temp->dscp_value != bpm->dscp_value || + bpm_temp->fragment != bpm->fragment) return HASHWALK_CONTINUE; /* look for remaining bpme */ @@ -1311,6 +1320,9 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp, dst_port = bpf->dst_port; pkt_len = bpf->pkt_len; + if (BGP_DEBUG(zebra, ZEBRA)) + bgp_pbr_dump_entry(bpf, false); + /* as we don't know information from EC * look for bpm that have the bpm * with vrf_id characteristics @@ -1581,6 +1593,101 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp, list_delete_all_node(bpof->fragment); } +static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add) +{ + struct bgp_pbr_range_port *src_port; + struct bgp_pbr_range_port *dst_port; + struct bgp_pbr_range_port *pkt_len; + char bufsrc[64], bufdst[64]; + char buffer[64]; + int remaining_len = 0; + char protocol_str[16]; + + if (!bpf) + return; + src_port = bpf->src_port; + dst_port = bpf->dst_port; + pkt_len = bpf->pkt_len; + + protocol_str[0] = '\0'; + if (bpf->tcp_flags && bpf->tcp_flags->mask) + bpf->protocol = IPPROTO_TCP; + if (bpf->protocol) + snprintf(protocol_str, sizeof(protocol_str), + "proto %d", bpf->protocol); + buffer[0] = '\0'; + if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port) + remaining_len += snprintf(buffer, sizeof(buffer), + "type %d, code %d", + src_port->min_port, + dst_port->min_port); + else if (bpf->protocol == IPPROTO_UDP || + bpf->protocol == IPPROTO_TCP) { + + if (src_port && src_port->min_port) + remaining_len += snprintf(buffer, + sizeof(buffer), + "from [%u:%u]", + src_port->min_port, + src_port->max_port ? + src_port->max_port : + src_port->min_port); + if (dst_port && dst_port->min_port) + remaining_len += snprintf(buffer + + remaining_len, + sizeof(buffer) + - remaining_len, + "to [%u:%u]", + dst_port->min_port, + dst_port->max_port ? + dst_port->max_port : + dst_port->min_port); + } + if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) { + remaining_len += snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + " len [%u:%u]", + pkt_len->min_port, + pkt_len->max_port ? + pkt_len->max_port : + pkt_len->min_port); + } else if (bpf->pkt_len_val) { + remaining_len += snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + " %s len %u", + bpf->pkt_len_val->mask + ? "!" : "", + bpf->pkt_len_val->val); + } + if (bpf->tcp_flags) { + remaining_len += snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + "tcpflags %x/%x", + bpf->tcp_flags->val, + bpf->tcp_flags->mask); + } + if (bpf->dscp) { + snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + "%s dscp %d", + bpf->dscp->mask + ? "!" : "", + bpf->dscp->val); + } + zlog_info("BGP: %s FS PBR from %s to %s, %s %s", + add ? "adding" : "removing", + bpf->src == NULL ? "<all>" : + prefix2str(bpf->src, bufsrc, sizeof(bufsrc)), + bpf->dst == NULL ? "<all>" : + prefix2str(bpf->dst, bufdst, sizeof(bufdst)), + protocol_str, buffer); + +} + static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct bgp_info *binfo, struct bgp_pbr_filter *bpf, @@ -1597,6 +1704,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct bgp_pbr_range_port *src_port; struct bgp_pbr_range_port *dst_port; struct bgp_pbr_range_port *pkt_len; + bool bpme_found = false; if (!bpf) return; @@ -1604,87 +1712,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, dst_port = bpf->dst_port; pkt_len = bpf->pkt_len; - if (BGP_DEBUG(zebra, ZEBRA)) { - char bufsrc[64], bufdst[64]; - char buffer[64]; - int remaining_len = 0; - char protocol_str[16]; - - protocol_str[0] = '\0'; - if (bpf->tcp_flags && bpf->tcp_flags->mask) - bpf->protocol = IPPROTO_TCP; - if (bpf->protocol) - snprintf(protocol_str, sizeof(protocol_str), - "proto %d", bpf->protocol); - buffer[0] = '\0'; - if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port) - remaining_len += snprintf(buffer, sizeof(buffer), - "type %d, code %d", - src_port->min_port, dst_port->min_port); - else if (bpf->protocol == IPPROTO_UDP || - bpf->protocol == IPPROTO_TCP) { - - if (src_port && src_port->min_port) - remaining_len += snprintf(buffer, - sizeof(buffer), - "from [%u:%u]", - src_port->min_port, - src_port->max_port ? - src_port->max_port : - src_port->min_port); - if (dst_port && dst_port->min_port) - remaining_len += snprintf(buffer + - remaining_len, - sizeof(buffer) - - remaining_len, - "to [%u:%u]", - dst_port->min_port, - dst_port->max_port ? - dst_port->max_port : - dst_port->min_port); - } - if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) { - remaining_len += snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - " len [%u:%u]", - pkt_len->min_port, - pkt_len->max_port ? - pkt_len->max_port : - pkt_len->min_port); - } else if (bpf->pkt_len_val) { - remaining_len += snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - " %s len %u", - bpf->pkt_len_val->mask - ? "!" : "", - bpf->pkt_len_val->val); - } - if (bpf->tcp_flags) { - remaining_len += snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - "tcpflags %x/%x", - bpf->tcp_flags->val, - bpf->tcp_flags->mask); - } - if (bpf->dscp) { - snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - "%s dscp %d", - bpf->dscp->mask - ? "!" : "", - bpf->dscp->val); - } - zlog_info("BGP: adding FS PBR from %s to %s, %s %s", - bpf->src == NULL ? "<all>" : - prefix2str(bpf->src, bufsrc, sizeof(bufsrc)), - bpf->dst == NULL ? "<all>" : - prefix2str(bpf->dst, bufdst, sizeof(bufdst)), - protocol_str, buffer); - } + if (BGP_DEBUG(zebra, ZEBRA)) + bgp_pbr_dump_entry(bpf, true); + /* look for bpa first */ memset(&temp3, 0, sizeof(temp3)); if (rate) @@ -1817,8 +1847,21 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, bpme->install_in_progress = false; /* link bgp info to bpme */ bpme->bgp_info = (void *)binfo; - } + } else + bpme_found = true; + /* already installed */ + if (bpme_found && bpme) { + struct bgp_info_extra *extra = bgp_info_extra_get(binfo); + + if (extra && extra->bgp_fs_pbr && + listnode_lookup(extra->bgp_fs_pbr, bpme)) { + if (BGP_DEBUG(pbr, PBR_ERROR)) + zlog_err("%s: entry %p/%p already installed in bgp pbr", + __func__, binfo, bpme); + return; + } + } /* BGP FS: append entry to zebra * - policies are not routing entries and as such * route replace semantics don't necessarily follow @@ -2195,7 +2238,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p, bool nlri_update) { struct bgp_pbr_entry_main api; - struct bgp_info_extra *extra = bgp_info_extra_get(info); if (afi == AFI_IP6) return; /* IPv6 not supported */ @@ -2212,13 +2254,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p, __func__); return; } - /* already installed */ - if (nlri_update && extra->bgp_fs_pbr) { - if (BGP_DEBUG(pbr, PBR_ERROR)) - zlog_err("%s: entry %p already installed in bgp pbr", - __func__, info); - return; - } if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) { if (BGP_DEBUG(pbr, PBR_ERROR)) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f10f7425c6..4bbc535cdc 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -188,14 +188,17 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra) struct bgp_info *bi = (struct bgp_info *)e->parent; if (bi->net) - bgp_unlock_node((struct bgp_node *)bi->net); - bi->net = NULL; + bi->net = bgp_unlock_node((struct bgp_node *)bi->net); bgp_info_unlock(e->parent); e->parent = NULL; } if (e->bgp_orig) bgp_unlock(e->bgp_orig); + + if ((*extra)->bgp_fs_pbr) + list_delete_all_node((*extra)->bgp_fs_pbr); + (*extra)->bgp_fs_pbr = NULL; XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra); *extra = NULL; @@ -8789,17 +8792,11 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, bgp_unlock_node(rm); } } else if (safi == SAFI_FLOWSPEC) { - rn = bgp_flowspec_get_match_per_ip(afi, rib, - &match, prefix_check); - if (rn != NULL) { - route_vty_out_flowspec(vty, &rn->p, - rn->info, use_json ? - NLRI_STRING_FORMAT_JSON : - NLRI_STRING_FORMAT_LARGE, - json_paths); - display++; - bgp_unlock_node(rn); - } + display = bgp_flowspec_display_match_per_ip(afi, rib, + &match, prefix_check, + vty, + use_json, + json_paths); } else { header = 1; @@ -10101,6 +10098,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, json_object *json_ocode = NULL; json_object *json_ar = NULL; struct peer_af *paf; + bool route_filtered; if (use_json) { json_scode = json_object_new_object(); @@ -10223,17 +10221,27 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, } bgp_attr_dup(&attr, ain->attr); + route_filtered = false; + + /* Filter prefix using distribute list, + * filter list or prefix list + */ + if ((bgp_input_filter(peer, &rn->p, &attr, afi, + safi)) == FILTER_DENY) + route_filtered = true; + + /* Filter prefix using route-map */ ret = bgp_input_modifier(peer, &rn->p, &attr, - afi, safi, rmap_name); + afi, safi, rmap_name); - if (type == bgp_show_adj_route_filtered - && ret != RMAP_DENY) { + if (type == bgp_show_adj_route_filtered && + !route_filtered && ret != RMAP_DENY) { bgp_attr_undup(&attr, ain->attr); continue; } - if (type == bgp_show_adj_route_received - && ret == RMAP_DENY) + if (type == bgp_show_adj_route_received && + (route_filtered || ret == RMAP_DENY)) filtered_count++; route_vty_out_tmp(vty, &rn->p, &attr, safi, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 72923901b8..dfef9a8f79 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -147,7 +147,7 @@ struct bgp_info_extra { */ struct prefix nexthop_orig; /* presence of FS pbr entry */ - void *bgp_fs_pbr; + struct list *bgp_fs_pbr; }; struct bgp_info { diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 60c2cbd4a4..f7eac09546 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node) /* * bgp_unlock_node */ -static inline void bgp_unlock_node(struct bgp_node *node) +static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node) { - route_unlock_node(bgp_node_to_rnode(node)); + return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node)); } /* diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index d555006571..1f80470f59 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -662,8 +662,7 @@ void subgroup_announce_route(struct update_subgroup *subgrp) void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) { struct bgp *bgp; - struct attr attr; - struct aspath *aspath; + struct bgp_info *info, init_info; struct prefix p; struct peer *from; struct bgp_node *rn; @@ -686,48 +685,50 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) bgp = peer->bgp; from = bgp->peer_self; - bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); - aspath = attr.aspath; - - attr.local_pref = bgp->default_local_pref; + init_info.attr = NULL; + info = &init_info; memset(&p, 0, sizeof(p)); p.family = afi2family(afi); p.prefixlen = 0; - if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) { - /* IPv6 global nexthop must be included. */ - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - - /* If the peer is on shared nextwork and we have link-local - nexthop set it. */ - if (peer->shared_network - && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local)) - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } - if (peer->default_rmap[afi][safi].name) { SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { for (ri = rn->info; ri; ri = ri->next) { - struct attr dummy_attr; - struct bgp_info info; - - /* Provide dummy so the route-map can't modify - * the attributes */ - bgp_attr_dup(&dummy_attr, ri->attr); - info.peer = ri->peer; - info.attr = &dummy_attr; + struct bgp_info tmp_info; + + tmp_info.peer = ri->peer; + tmp_info.attr = ri->attr; + + /* Reset attributes every time to avoid \ + * unexpected as-path prepends */ + bgp_attr_default_set(tmp_info.attr, + BGP_ORIGIN_IGP); + + if ((afi == AFI_IP6) + || peer_cap_enhe(peer, afi, safi)) { + /* IPv6 global nexthop must be included. + */ + tmp_info.attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL; + + /* If the peer is on shared nextwork and + * we have link-local nexthop set it. */ + if (peer->shared_network + && !IN6_IS_ADDR_UNSPECIFIED( + &peer->nexthop.v6_local)) + tmp_info.attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + } ret = route_map_apply( peer->default_rmap[afi][safi].map, - &rn->p, RMAP_BGP, &info); + &rn->p, RMAP_BGP, &tmp_info); + + info = &tmp_info; - /* The route map might have set attributes. If - * we don't flush them - * here, they will be leaked. */ - bgp_attr_flush(&dummy_attr); if (ret != RMAP_DENYMATCH) break; } @@ -749,12 +750,13 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) SUBGRP_STATUS_DEFAULT_ORIGINATE)) { if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { - bgp_attr_add_gshut_community(&attr); + bgp_attr_add_gshut_community(info->attr); } SET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - subgroup_default_update_packet(subgrp, &attr, from); + subgroup_default_update_packet(subgrp, info->attr, + from); /* The 'neighbor x.x.x.x default-originate' default will * act as an @@ -774,8 +776,6 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); } } - - aspath_unintern(&aspath); } /* diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 714f6791c1..9591fe673f 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1998,7 +1998,7 @@ static int ipset_notify_owner(int command, struct zclient *zclient, bgp_pbim = bgp_pbr_match_ipset_lookup(vrf_id, unique); if (!bgp_pbim) { if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: Fail to look BGP match ( %u %u)", + zlog_debug("%s: Fail to look BGP match ( %u, ID %u)", __PRETTY_FUNCTION__, note, unique); return 0; } @@ -2048,7 +2048,7 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient, unique); if (!bgp_pbime) { if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: Fail to look BGP match entry (%u %u)", + zlog_debug("%s: Fail to look BGP match entry (%u, ID %u)", __PRETTY_FUNCTION__, note, unique); return 0; } @@ -2074,7 +2074,9 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient, /* link bgp_info to bpme */ bgp_info = (struct bgp_info *)bgp_pbime->bgp_info; extra = bgp_info_extra_get(bgp_info); - extra->bgp_fs_pbr = (void *)bgp_pbime; + if (extra->bgp_fs_pbr == NULL) + extra->bgp_fs_pbr = list_new(); + listnode_add(extra->bgp_fs_pbr, bgp_pbime); } break; case ZAPI_IPSET_ENTRY_FAIL_REMOVE: @@ -2587,9 +2589,10 @@ void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install) if (pbrim->install_in_progress) return; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: name %s type %d %d", + zlog_debug("%s: name %s type %d %d, ID %u", __PRETTY_FUNCTION__, - pbrim->ipset_name, pbrim->type, install); + pbrim->ipset_name, pbrim->type, + install, pbrim->unique); s = zclient->obuf; stream_reset(s); @@ -2615,9 +2618,9 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime, if (pbrime->install_in_progress) return; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: name %s %d %d", __PRETTY_FUNCTION__, + zlog_debug("%s: name %s %d %d, ID %u", __PRETTY_FUNCTION__, pbrime->backpointer->ipset_name, - pbrime->unique, install); + pbrime->unique, install, pbrime->unique); s = zclient->obuf; stream_reset(s); @@ -2682,9 +2685,10 @@ void bgp_send_pbr_iptable(struct bgp_pbr_action *pba, if (pbm->install_iptable_in_progress) return; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: name %s type %d mark %d %d", + zlog_debug("%s: name %s type %d mark %d %d, ID %u", __PRETTY_FUNCTION__, pbm->ipset_name, - pbm->type, pba->fwmark, install); + pbm->type, pba->fwmark, install, + pbm->unique2); s = zclient->obuf; stream_reset(s); diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 579b0b6497..734c9cabd0 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -31,9 +31,9 @@ be specified (:ref:`common-invocation-options`). .. option:: -l, --listenon - Specify a specific IP address for bgpd to listen on, rather than its - default of INADDR_ANY / IN6ADDR_ANY. This can be useful to constrain bgpd - to an internal address, or to run multiple bgpd processes on one host. + Specify a specific IP address for bgpd to listen on, rather than its default + of ``0.0.0.0`` / ``::``. This can be useful to constrain bgpd to an internal + address, or to run multiple bgpd processes on one host. .. _bgp-basic-concepts: @@ -45,26 +45,33 @@ Basic Concepts Autonomous Systems ------------------ -The :abbr:`AS (Autonomous System)` number is one of the essential element of +From :rfc:`1930`: + + An AS is a connected group of one or more IP prefixes run by one or more + network operators which has a SINGLE and CLEARLY DEFINED routing policy. + +Each AS has an identifying number associated with it called an :abbr:`ASN +(Autonomous System Number)`. This is a two octet value ranging in value from 1 +to 65535. The AS numbers 64512 through 65535 are defined as private AS numbers. +Private AS numbers must not be advertised on the global Internet. + +The :abbr:`ASN (Autonomous System Number)` is one of the essential elements of BGP. BGP is a distance vector routing protocol, and the AS-Path framework -provides distance vector metric and loop detection to BGP. :rfc:`1930` provides -some background on the concepts of an AS. +provides distance vector metric and loop detection to BGP. -The AS number is a two octet value, ranging in value from 1 to 65535. The AS -numbers 64512 through 65535 are defined as private AS numbers. Private AS -numbers must not to be advertised in the global Internet. +.. seealso:: :rfc:`1930` .. _bgp-address-families: Address Families ---------------- -Multiprotocol BGP enables BGP to carry routing information for multiple Network -Layer protocols. BGP supports an Address Family Identifier (AFI) for IPv4 and -IPv6. Support is also provided for multiple sets of per-AFI information via the -BGP Subsequent Address Family Identifier (SAFI). FRR supports SAFIs for unicast -information, labeled information :rfc:`3107` and :rfc:`8277`, and Layer 3 VPN -information :rfc:`4364` and :rfc:`4659`. +Multiprotocol extensions enable BGP to carry routing information for multiple +network layer protocols. BGP supports an Address Family Identifier (AFI) for +IPv4 and IPv6. Support is also provided for multiple sets of per-AFI +information via the BGP Subsequent Address Family Identifier (SAFI). FRR +supports SAFIs for unicast information, labeled information (:rfc:`3107` and +:rfc:`8277`), and Layer 3 VPN information (:rfc:`4364` and :rfc:`4659`). .. _bgp-route-selection: @@ -718,35 +725,30 @@ Defining Peers Configuring Peers ^^^^^^^^^^^^^^^^^ -.. index:: neighbor PEER shutdown -.. clicmd:: neighbor PEER shutdown - -.. index:: no neighbor PEER shutdown -.. clicmd:: no neighbor PEER shutdown +.. index:: [no] neighbor PEER shutdown +.. clicmd:: [no] neighbor PEER shutdown Shutdown the peer. We can delete the neighbor's configuration by ``no neighbor PEER remote-as ASN`` but all configuration of the neighbor will be deleted. When you want to preserve the configuration, but want to drop the BGP peer, use this syntax. -.. index:: neighbor PEER ebgp-multihop -.. clicmd:: neighbor PEER ebgp-multihop - -.. index:: no neighbor PEER ebgp-multihop -.. clicmd:: no neighbor PEER ebgp-multihop - +.. index:: [no] neighbor PEER disable-connected-check +.. clicmd:: [no] neighbor PEER disable-connected-check -.. index:: neighbor PEER description ... -.. clicmd:: neighbor PEER description ... + Allow peerings between directly connected eBGP peers using loopback + addresses. +.. index:: [no] neighbor PEER ebgp-multihop +.. clicmd:: [no] neighbor PEER ebgp-multihop -.. index:: no neighbor PEER description ... -.. clicmd:: no neighbor PEER description ... +.. index:: [no] neighbor PEER description ... +.. clicmd:: [no] neighbor PEER description ... Set description of the peer. -.. index:: neighbor PEER version VERSION -.. clicmd:: neighbor PEER version VERSION +.. index:: [no] neighbor PEER version VERSION +.. clicmd:: [no] neighbor PEER version VERSION Set up the neighbor's BGP version. `version` can be `4`, `4+` or `4-`. BGP version `4` is the default value used for BGP peering. BGP version `4+` @@ -755,12 +757,8 @@ Configuring Peers revision 00's Multiprotocol Extensions for BGP-4. Some routing software is still using this version. -.. index:: neighbor PEER interface IFNAME -.. clicmd:: neighbor PEER interface IFNAME - - -.. index:: no neighbor PEER interface IFNAME -.. clicmd:: no neighbor PEER interface IFNAME +.. index:: [no] neighbor PEER interface IFNAME +.. clicmd:: [no] neighbor PEER interface IFNAME When you connect to a BGP peer over an IPv6 link-local address, you have to specify the IFNAME of the interface used for the connection. To specify @@ -770,24 +768,16 @@ Configuring Peers This command is deprecated and may be removed in a future release. Its use should be avoided. -.. index:: neighbor PEER next-hop-self [all] -.. clicmd:: neighbor PEER next-hop-self [all] - - -.. index:: no neighbor PEER next-hop-self [all] -.. clicmd:: no neighbor PEER next-hop-self [all] +.. index:: [no] neighbor PEER next-hop-self [all] +.. clicmd:: [no] neighbor PEER next-hop-self [all] This command specifies an announced route's nexthop as being equivalent to the address of the bgp router if it is learned via eBGP. If the optional keyword `all` is specified the modification is done also for routes learned via iBGP. -.. index:: neighbor PEER update-source <IFNAME|ADDRESS> -.. clicmd:: neighbor PEER update-source <IFNAME|ADDRESS> - - -.. index:: no neighbor PEER update-source -.. clicmd:: no neighbor PEER update-source +.. index:: [no] neighbor PEER update-source <IFNAME|ADDRESS> +.. clicmd:: [no] neighbor PEER update-source <IFNAME|ADDRESS> Specify the IPv4 source address to use for the :abbr:`BGP` session to this neighbour, may be specified as either an IPv4 address directly or as an @@ -801,11 +791,8 @@ Configuring Peers neighbor bar update-source lo0 -.. index:: neighbor PEER default-originate -.. clicmd:: neighbor PEER default-originate - -.. index:: no neighbor PEER default-originate -.. clicmd:: no neighbor PEER default-originate +.. index:: [no] neighbor PEER default-originate +.. clicmd:: [no] neighbor PEER default-originate *bgpd*'s default is to not announce the default route (0.0.0.0/0) even if it is in routing table. When you want to announce default routes to the peer, @@ -817,37 +804,22 @@ Configuring Peers .. index:: neighbor PEER send-community .. clicmd:: neighbor PEER send-community -.. index:: neighbor PEER weight WEIGHT -.. clicmd:: neighbor PEER weight WEIGHT - - -.. index:: no neighbor PEER weight WEIGHT -.. clicmd:: no neighbor PEER weight WEIGHT +.. index:: [no] neighbor PEER weight WEIGHT +.. clicmd:: [no] neighbor PEER weight WEIGHT This command specifies a default `weight` value for the neighbor's routes. -.. index:: neighbor PEER maximum-prefix NUMBER -.. clicmd:: neighbor PEER maximum-prefix NUMBER - - -.. index:: no neighbor PEER maximum-prefix NUMBER -.. clicmd:: no neighbor PEER maximum-prefix NUMBER - +.. index:: [no] neighbor PEER maximum-prefix NUMBER +.. clicmd:: [no] neighbor PEER maximum-prefix NUMBER -.. index:: neighbor PEER local-as AS-NUMBER -.. clicmd:: neighbor PEER local-as AS-NUMBER +.. index:: [no] neighbor PEER local-as AS-NUMBER no-prepend +.. clicmd:: [no] neighbor PEER local-as AS-NUMBER no-prepend +.. index:: [no] neighbor PEER local-as AS-NUMBER no-prepend replace-as +.. clicmd:: [no] neighbor PEER local-as AS-NUMBER no-prepend replace-as -.. index:: neighbor PEER local-as AS-NUMBER no-prepend -.. clicmd:: neighbor PEER local-as AS-NUMBER no-prepend - - -.. index:: neighbor PEER local-as AS-NUMBER no-prepend replace-as -.. clicmd:: neighbor PEER local-as AS-NUMBER no-prepend replace-as - - -.. index:: no neighbor PEER local-as -.. clicmd:: no neighbor PEER local-as +.. index:: [no] neighbor PEER local-as AS-NUMBER +.. clicmd:: [no] neighbor PEER local-as AS-NUMBER Specify an alternate AS for this BGP process when interacting with the specified peer. With no modifiers, the specified local-as is prepended to @@ -865,12 +837,8 @@ Configuring Peers This command is only allowed for eBGP peers. -.. index:: neighbor PEER ttl-security hops NUMBER -.. clicmd:: neighbor PEER ttl-security hops NUMBER - - -.. index:: no neighbor PEER ttl-security hops NUMBER -.. clicmd:: no neighbor PEER ttl-security hops NUMBER +.. index:: [no] neighbor PEER ttl-security hops NUMBER +.. clicmd:: [no] neighbor PEER ttl-security hops NUMBER This command enforces Generalized TTL Security Mechanism (GTSM), as specified in RFC 5082. With this command, only neighbors that are the diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst index 38b2b68e98..4f271dee74 100644 --- a/doc/user/rpki.rst +++ b/doc/user/rpki.rst @@ -60,39 +60,41 @@ Enabling RPKI This command enables the RPKI configuration mode. Most commands that start with *rpki* can only be used in this mode. - When it is used in a telnet session, leaving of this mode cause rpki to be initialized. + When it is used in a telnet session, leaving of this mode cause rpki to be + initialized. Executing this command alone does not activate prefix validation. You need to configure at least one reachable cache server. See section :ref:`configuring-rpki-rtr-cache-servers` for configuring a cache server. -.. _configuring-rpki-rtr-cache-servers: - .. index:: daemons.conf - When first installing FRR with RPKI support from the pre-packaged binaries. Remember - to append '-M rpki' in the /etc/frr/daemons.conf file to the bgpd_options. - - bgpd_options=" --daemon -A 127.0.0.1 -M rpki" - instead of the default setting - bgpd_options=" --daemon -A 127.0.0.1" - - - Else you will encounter an error when trying to enter RPKI configuration mode. Because - the rpki module is not loaded when the BGP daemon is initialized. - - Examples of the error: - - router(config)# debug rpki - % [BGP] Unknown command: debug rpki - - router(config)# rpki - % [BGP] Unknown command: rpki - - Note that the rpki commands will be available in vtysh when running 'find rpki'. - Even if the RPKI module is NOT loaded. - The RPKI commands will be unavailable if you try running the same command in the - cli specific to the BGP daemon. + When first installing FRR with RPKI support from the pre-packaged binaries. + Remember to append :option:`-M rpki` in the :file:`/etc/frr/daemons.conf` + file to ``bgpd_options``, like so:: + + bgpd_options=" --daemon -A 127.0.0.1 -M rpki" + + instead of the default setting:: + + bgpd_options=" --daemon -A 127.0.0.1" + + Otherwise you will encounter an error when trying to enter RPKI + configuration mode due to the ``rpki`` module not being loaded when the BGP + daemon is initialized. + + Examples of the error:: + + router(config)# debug rpki + % [BGP] Unknown command: debug rpki + + router(config)# rpki + % [BGP] Unknown command: rpki + + Note that the RPKI commands will be available in vtysh when running ``find + rpki`` regardless of whether the module is loaded. + +.. _configuring-rpki-rtr-cache-servers: Configuring RPKI/RTR Cache Servers ---------------------------------- diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 08606c2128..a9431b16e3 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -463,7 +463,7 @@ commands in relationship to VRF. Here is an extract of some of those commands: .. clicmd:: vrf VRF This command is available on configuration mode. By default, above command - permits accessing the vrf configuration mode. This mode is available for + permits accessing the VRF configuration mode. This mode is available for both VRFs. It is to be noted that *Zebra* does not create Linux VRF. The network administrator can however decide to provision this command in configuration file to provide more clarity about the intended configuration. @@ -493,7 +493,10 @@ commands in relationship to VRF. Here is an extract of some of those commands: This command is based on configuration mode. There, for default VRF, this command is available for all modes. The ``TABLENO`` configured is one of the - tables from Default *Linux network namespace*. + tables from Default *Linux network namespace*. This command is also available + on vrf configuration mode, provided that *Zebra* is run with :option:`-n` + option. In that case, this command configures a network route in the given + ``TABLENO`` of the *Linux network namespace* of the relevant VRF. .. index:: show ip route vrf VRF .. clicmd:: show ip route vrf VRF @@ -652,7 +652,7 @@ DEFUN (interface, /*Pending: need proper vrf name based lookup/(possible creation of VRF) Imagine forward reference of a vrf by name in this interface config */ if (vrfname) - VRF_GET_ID(vrf_id, vrfname); + VRF_GET_ID(vrf_id, vrfname, false); #ifdef SUNOS_5 ifp = if_sunwzebra_get(ifname, vrf_id); @@ -686,7 +686,7 @@ DEFUN_NOSH (no_interface, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 3) - VRF_GET_ID(vrf_id, vrfname); + VRF_GET_ID(vrf_id, vrfname, false); ifp = if_lookup_by_name(ifname, vrf_id); diff --git a/lib/table.h b/lib/table.h index 8304abe59b..ac7df3e695 100644 --- a/lib/table.h +++ b/lib/table.h @@ -235,13 +235,17 @@ static inline struct route_node *route_lock_node(struct route_node *node) } /* Unlock node. */ -static inline void route_unlock_node(struct route_node *node) +static inline struct route_node *route_unlock_node(struct route_node *node) { assert(node->lock > 0); (*(unsigned *)&node->lock)--; - if (node->lock == 0) + if (node->lock == 0) { route_node_delete(node); + return NULL; + } + + return node; } /* @@ -111,15 +111,24 @@ extern struct vrf *vrf_get(vrf_id_t, const char *); extern const char *vrf_id_to_name(vrf_id_t vrf_id); extern vrf_id_t vrf_name_to_id(const char *); -#define VRF_GET_ID(V, NAME) \ +#define VRF_GET_ID(V, NAME, USE_JSON) \ do { \ struct vrf *vrf; \ if (!(vrf = vrf_lookup_by_name(NAME))) { \ + if (USE_JSON) { \ + vty_out(vty, "{}\n"); \ + } else { \ + vty_out(vty, "%% VRF %s not found\n", NAME); \ + } \ vty_out(vty, "%% VRF %s not found\n", NAME); \ return CMD_WARNING; \ } \ if (vrf->vrf_id == VRF_UNKNOWN) { \ - vty_out(vty, "%% VRF %s not active\n", NAME); \ + if (USE_JSON) { \ + vty_out(vty, "{}\n"); \ + } else { \ + vty_out(vty, "%% VRF %s not active\n", NAME); \ + } \ return CMD_WARNING; \ } \ (V) = vrf->vrf_id; \ diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 5d4ddf14e8..63688f87e0 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -114,7 +114,7 @@ size_t pim_msg_get_jp_group_size(struct list *sources) size += sizeof(struct pim_encoded_source_ipv4) * sources->count; js = listgetdata(listhead(sources)); - if (js && js->up->sg.src.s_addr == INADDR_ANY) { + if (js && js->up->sg.src.s_addr == INADDR_ANY && js->is_join) { struct pim_upstream *child, *up; struct listnode *up_node; diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c index 01ce7480d7..a0382827b9 100644 --- a/tests/bgpd/test_bgp_table.c +++ b/tests/bgpd/test_bgp_table.c @@ -116,8 +116,8 @@ static void check_lookup_result(struct list *list, va_list arglist) assert(prefix_count == listcount(list)); } -static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen, - ...) +static void do_test(struct bgp_table *table, const char *prefix, + uint32_t maxlen, ...) { va_list arglist; struct list *list = list_new(); diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index c75a699a16..4612bdc26b 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -821,6 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type) switch (type) { case CAPABILITY: len += 2; /* to cover the OPT-Param header */ + __attribute__ ((fallthrough)); case OPT_PARAM: printf("len: %u\n", len); /* peek_for_as4 wants getp at capibility*/ diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c index 53180564bd..e717da15b3 100644 --- a/tests/lib/test_srcdest_table.c +++ b/tests/lib/test_srcdest_table.c @@ -392,7 +392,8 @@ static void test_state_del_one_route(struct test_state *test, struct prng *prng) } assert(rn); - srcdest_rnode_prefixes(rn, &dst_p, &src_p); + srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p, + (const struct prefix **)&src_p); memcpy(&dst6_p, dst_p, sizeof(dst6_p)); if (src_p) memcpy(&src6_p, src_p, sizeof(src6_p)); diff --git a/zebra/interface.c b/zebra/interface.c index 6125ff9a16..1067f9bdc1 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1417,7 +1417,7 @@ DEFUN (show_interface, interface_update_stats(); if (argc > 2) - VRF_GET_ID(vrf_id, argv[3]->arg); + VRF_GET_ID(vrf_id, argv[3]->arg, false); /* All interface print. */ vrf = vrf_lookup_by_id(vrf_id); @@ -1466,7 +1466,7 @@ DEFUN (show_interface_name_vrf, interface_update_stats(); - VRF_GET_ID(vrf_id, argv[idx_name]->arg); + VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); /* Specified interface print. */ ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); @@ -1560,7 +1560,7 @@ DEFUN (show_interface_desc, vrf_id_t vrf_id = VRF_DEFAULT; if (argc > 3) - VRF_GET_ID(vrf_id, argv[4]->arg); + VRF_GET_ID(vrf_id, argv[4]->arg, false); if_show_description(vty, vrf_id); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 8703b01319..cd881dcc24 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -638,7 +638,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), read_in++; for (h = (struct nlmsghdr *)buf; - NLMSG_OK(h, (unsigned int)status); + (status >= 0 && NLMSG_OK(h, (unsigned int)status)); h = NLMSG_NEXT(h, status)) { /* Finish of reading. */ if (h->nlmsg_type == NLMSG_DONE) diff --git a/zebra/router-id.c b/zebra/router-id.c index 252b558a8b..3b96b3371d 100644 --- a/zebra/router-id.c +++ b/zebra/router-id.c @@ -226,7 +226,7 @@ DEFUN (router_id, rid.family = AF_INET; if (argc > 2) - VRF_GET_ID(vrf_id, argv[idx_name]->arg); + VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); router_id_set(&rid, vrf_id); @@ -251,7 +251,7 @@ DEFUN (no_router_id, rid.family = AF_INET; if (argc > 3) - VRF_GET_ID(vrf_id, argv[idx_name]->arg); + VRF_GET_ID(vrf_id, argv[idx_name]->arg, false); router_id_set(&rid, vrf_id); diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 74ef25b031..e2217a5d2b 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -832,6 +832,7 @@ struct zebra_pbr_ipset_entry_unique_display { struct zebra_pbr_env_display { struct zebra_ns *zns; struct vty *vty; + char *name; }; static const char *zebra_pbr_prefix2str(union prefixconstptr pu, @@ -1037,6 +1038,7 @@ void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname) } uniqueipset.zns = zns; uniqueipset.vty = vty; + uniqueipset.name = NULL; hash_walk(zns->ipset_hash, zebra_pbr_show_ipset_walkcb, &uniqueipset); } @@ -1060,19 +1062,25 @@ static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet *backet, return HASHWALK_CONTINUE; } -static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg) +static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable, + struct vty *vty, + struct zebra_ns *zns) { - struct zebra_pbr_iptable *iptable = - (struct zebra_pbr_iptable *)backet->data; - struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg; - struct vty *vty = env->vty; - struct zebra_ns *zns = env->zns; int ret; uint64_t pkts = 0, bytes = 0; vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name, iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect", iptable->unique); + if (iptable->type == IPSET_NET_PORT || + iptable->type == IPSET_NET_PORT_NET) { + if (!(iptable->filter_bm & MATCH_ICMP_SET)) { + if (iptable->filter_bm & PBR_FILTER_DST_PORT) + vty_out(vty, "\t lookup dst port\n"); + else if (iptable->filter_bm & PBR_FILTER_SRC_PORT) + vty_out(vty, "\t lookup src port\n"); + } + } if (iptable->pkt_len_min || iptable->pkt_len_max) { if (!iptable->pkt_len_max) vty_out(vty, "\t pkt len %u\n", @@ -1129,17 +1137,34 @@ static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg) prfl.fwmark); } } +} + +static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg) +{ + struct zebra_pbr_iptable *iptable = + (struct zebra_pbr_iptable *)backet->data; + struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg; + struct vty *vty = env->vty; + struct zebra_ns *zns = env->zns; + char *iptable_name = env->name; + + if (!iptable_name) + zebra_pbr_show_iptable_unit(iptable, vty, zns); + else if (!strncmp(iptable_name, + iptable->ipset_name, + ZEBRA_IPSET_NAME_SIZE)) + zebra_pbr_show_iptable_unit(iptable, vty, zns); return HASHWALK_CONTINUE; } -void zebra_pbr_show_iptable(struct vty *vty) +void zebra_pbr_show_iptable(struct vty *vty, char *iptable_name) { struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_pbr_env_display env; env.vty = vty; env.zns = zns; - + env.name = iptable_name; hash_walk(zns->iptable_hash, zebra_pbr_show_iptable_walkcb, &env); } diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index fd83502ae1..0db33d1f8c 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -235,7 +235,7 @@ extern int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2); extern void zebra_pbr_init(void); extern void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname); -extern void zebra_pbr_show_iptable(struct vty *vty); +extern void zebra_pbr_show_iptable(struct vty *vty, char *iptable); extern void zebra_pbr_iptable_update_interfacelist(struct stream *s, struct zebra_pbr_iptable *zpi); size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len, diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 8ee47d2f1b..4d71682f64 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1071,7 +1071,7 @@ DEFPY(ip_route_vrf, return zebra_static_route_leak( vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, - NULL); + table_str); } /* New RIB. Detailed information for IPv4 route. */ @@ -1808,7 +1808,7 @@ DEFPY (show_route_table_vrf, vrf_id_t vrf_id = VRF_DEFAULT; if (vrf_name) - VRF_GET_ID(vrf_id, vrf_name); + VRF_GET_ID(vrf_id, vrf_name, !!json); zvrf = zebra_vrf_lookup_by_id(vrf_id); t = zebra_ns_find_table(zvrf->zns, table, afi); @@ -1831,7 +1831,7 @@ DEFUN (show_ip_nht, vrf_id_t vrf_id = VRF_DEFAULT; if (argc == 5) - VRF_GET_ID(vrf_id, argv[idx_vrf]->arg); + VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false); zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); return CMD_SUCCESS; @@ -1871,7 +1871,7 @@ DEFUN (show_ipv6_nht, vrf_id_t vrf_id = VRF_DEFAULT; if (argc == 5) - VRF_GET_ID(vrf_id, argv[idx_vrf]->arg); + VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false); zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); return CMD_SUCCESS; @@ -2037,7 +2037,7 @@ DEFPY (show_route, vrf_id_t vrf_id = VRF_DEFAULT; if (vrf_name) - VRF_GET_ID(vrf_id, vrf_name); + VRF_GET_ID(vrf_id, vrf_name, !!json); vrf = vrf_lookup_by_id(vrf_id); do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib, !!json, tag, prefix_str ? prefix : NULL, @@ -2111,7 +2111,7 @@ DEFPY (show_route_detail, vrf_id_t vrf_id = VRF_DEFAULT; if (vrf_name) - VRF_GET_ID(vrf_id, vrf_name); + VRF_GET_ID(vrf_id, vrf_name, false); table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); if (!table) @@ -2178,7 +2178,7 @@ DEFPY (show_route_summary, vrf_id_t vrf_id = VRF_DEFAULT; if (vrf_name) - VRF_GET_ID(vrf_id, vrf_name); + VRF_GET_ID(vrf_id, vrf_name, false); table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id); if (!table) @@ -2793,7 +2793,7 @@ DEFUN (show_ipv6_mroute, vrf_id_t vrf_id = VRF_DEFAULT; if (argc == 5) - VRF_GET_ID(vrf_id, argv[4]->arg); + VRF_GET_ID(vrf_id, argv[4]->arg, false); table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id); if (!table) @@ -3474,12 +3474,20 @@ DEFUN (show_pbr_ipset, /* policy routing contexts */ DEFUN (show_pbr_iptable, show_pbr_iptable_cmd, - "show pbr iptable", + "show pbr iptable [WORD]", SHOW_STR "Policy-Based Routing\n" - "IPtable Context information\n") + "IPtable Context information\n" + "IPtable Name information\n") { - zebra_pbr_show_iptable(vty); + int idx = 0; + int found = 0; + + found = argv_find(argv, argc, "WORD", &idx); + if (!found) + zebra_pbr_show_iptable(vty, NULL); + else + zebra_pbr_show_iptable(vty, argv[idx]->arg); return CMD_SUCCESS; } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 06d1b3618c..4955f3f77c 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -244,6 +244,7 @@ static uint32_t num_valid_macs(zebra_vni_t *zvni) for (hb = hash->index[i]; hb; hb = hb->next) { mac = (zebra_mac_t *)hb->data; if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) + || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) || !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) num_macs++; } |
