diff options
34 files changed, 655 insertions, 252 deletions
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index 75be3c79fe..0d2f84bfc4 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -3146,8 +3146,7 @@ int bgp_neighbors_neighbor_neighbor_remote_as_remote_as_type_modify( return NB_OK; str2sockunion(peer_str, &su); - ret = peer_remote_as(bgp, &su, NULL, &as, as_type, AFI_IP, - SAFI_UNICAST); + ret = peer_remote_as(bgp, &su, NULL, &as, as_type); if (bgp_nb_errmsg_return(args->errmsg, args->errmsg_len, ret) < 0) return NB_ERR_INCONSISTENCY; @@ -3202,8 +3201,7 @@ int bgp_neighbors_neighbor_neighbor_remote_as_remote_as_modify( as = yang_dnode_get_uint32(args->dnode, NULL); str2sockunion(peer_str, &su); - ret = peer_remote_as(bgp, &su, NULL, &as, as_type, AFI_IP, - SAFI_UNICAST); + ret = peer_remote_as(bgp, &su, NULL, &as, as_type); if (bgp_nb_errmsg_return(args->errmsg, args->errmsg_len, ret) < 0) return NB_ERR_INCONSISTENCY; @@ -4370,8 +4368,7 @@ int bgp_neighbors_unnumbered_neighbor_create(struct nb_cb_create_args *args) "./neighbor-remote-as/remote-as"); } - if (peer_conf_interface_create(bgp, peer_str, AFI_IP, - SAFI_UNICAST, v6_only, + if (peer_conf_interface_create(bgp, peer_str, v6_only, peer_grp_str, as_type, as, args->errmsg, args->errmsg_len)) return NB_ERR_INCONSISTENCY; @@ -4440,9 +4437,9 @@ int bgp_neighbors_unnumbered_neighbor_v6only_modify( v6_only = yang_dnode_get_bool(args->dnode, NULL); - if (peer_conf_interface_create( - bgp, peer_str, AFI_IP, SAFI_UNICAST, v6_only, NULL, - AS_UNSPECIFIED, 0, args->errmsg, args->errmsg_len)) + if (peer_conf_interface_create(bgp, peer_str, v6_only, NULL, + AS_UNSPECIFIED, 0, args->errmsg, + args->errmsg_len)) return NB_ERR_INCONSISTENCY; break; @@ -5174,8 +5171,6 @@ void bgp_neighbors_unnumbered_neighbor_neighbor_remote_as_apply_finish( int ret; as_t as = 0; struct peer *peer = NULL; - afi_t afi = AFI_IP; - safi_t safi = SAFI_UNICAST; bgp = nb_running_get_entry(args->dnode, NULL, true); peer_str = yang_dnode_get_string(args->dnode, "../interface"); @@ -5185,7 +5180,7 @@ void bgp_neighbors_unnumbered_neighbor_neighbor_remote_as_apply_finish( peer = peer_lookup_by_conf_if(bgp, peer_str); - ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, afi, safi); + ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type); if (ret < 0 && !peer) { snprintf(args->errmsg, args->errmsg_len, diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 03ff27c7ca..4821ce8ddb 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -544,7 +544,7 @@ static int bgp_accept(struct thread *thread) peer1->host); peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, - peer1->as, peer1->as_type, 0, 0, NULL); + peer1->as, peer1->as_type, NULL); hash_release(peer->bgp->peerhash, peer); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6a44303339..a6c00d5735 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -3727,6 +3727,29 @@ DEFPY (no_bgp_bestpath_bw, return CMD_SUCCESS; } +/* "no bgp default ipv6-unicast". */ +DEFUN(no_bgp_default_ipv6_unicast, no_bgp_default_ipv6_unicast_cmd, + "no bgp default ipv6-unicast", NO_STR + "BGP specific commands\n" + "Configure BGP defaults\n" + "Activate ipv6-unicast for a peer by default\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + UNSET_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6); + return CMD_SUCCESS; +} + +DEFUN(bgp_default_ipv6_unicast, bgp_default_ipv6_unicast_cmd, + "bgp default ipv6-unicast", + "BGP specific commands\n" + "Configure BGP defaults\n" + "Activate ipv6-unicast for a peer by default\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + SET_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6); + return CMD_SUCCESS; +} + /* "no bgp default ipv4-unicast". */ DEFUN (no_bgp_default_ipv4_unicast, no_bgp_default_ipv4_unicast_cmd, @@ -4368,10 +4391,10 @@ DEFUN_YANG(neighbor_remote_as, return nb_cli_apply_changes(vty, base_xpath); } -int peer_conf_interface_create(struct bgp *bgp, const char *conf_if, afi_t afi, - safi_t safi, bool v6only, - const char *peer_group_name, int as_type, - as_t as, char *errmsg, size_t errmsg_len) +int peer_conf_interface_create(struct bgp *bgp, const char *conf_if, + bool v6only, const char *peer_group_name, + int as_type, as_t as, char *errmsg, + size_t errmsg_len) { struct peer *peer; struct peer_group *group; @@ -4388,16 +4411,10 @@ int peer_conf_interface_create(struct bgp *bgp, const char *conf_if, afi_t afi, peer = peer_lookup_by_conf_if(bgp, conf_if); if (peer) { if (as_type != AS_UNSPECIFIED) - ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type, - afi, safi); + ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type); } else { - if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4) - && afi == AFI_IP && safi == SAFI_UNICAST) - peer = peer_create(NULL, conf_if, bgp, bgp->as, as, - as_type, 0, 0, NULL); - else - peer = peer_create(NULL, conf_if, bgp, bgp->as, as, - as_type, afi, safi, NULL); + peer = peer_create(NULL, conf_if, bgp, bgp->as, as, as_type, + NULL); if (!peer) { snprintf(errmsg, errmsg_len, @@ -6139,10 +6156,28 @@ DEFUN_YANG (neighbor_send_community, "Send Community attribute to this neighbor\n") { int idx_peer = 1; + char *peer_str = argv[idx_peer]->arg; + char base_xpath[XPATH_MAXLEN]; + char af_xpath[XPATH_MAXLEN]; + char std_xpath[XPATH_MAXLEN]; + afi_t afi = bgp_node_afi(vty); + safi_t safi = bgp_node_safi(vty); - return peer_af_flag_set_vty(vty, argv[idx_peer]->arg, bgp_node_afi(vty), - bgp_node_safi(vty), - PEER_FLAG_SEND_COMMUNITY); + snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, + yang_afi_safi_value2identity(afi, safi)); + + if (peer_and_group_lookup_nb(vty, peer_str, base_xpath, + sizeof(base_xpath), af_xpath) + < 0) + return CMD_WARNING_CONFIG_FAILED; + + snprintf(std_xpath, sizeof(std_xpath), + "./%s/send-community/send-community", + bgp_afi_safi_get_container_str(afi, safi)); + + nb_cli_enqueue_change(vty, std_xpath, NB_OP_MODIFY, "true"); + + return nb_cli_apply_changes(vty, base_xpath); } ALIAS_HIDDEN(neighbor_send_community, neighbor_send_community_hidden_cmd, @@ -6159,10 +6194,28 @@ DEFUN_YANG (no_neighbor_send_community, "Send Community attribute to this neighbor\n") { int idx_peer = 2; + char *peer_str = argv[idx_peer]->arg; + char base_xpath[XPATH_MAXLEN]; + char af_xpath[XPATH_MAXLEN]; + char std_xpath[XPATH_MAXLEN]; + afi_t afi = bgp_node_afi(vty); + safi_t safi = bgp_node_safi(vty); - return peer_af_flag_unset_vty(vty, argv[idx_peer]->arg, - bgp_node_afi(vty), bgp_node_safi(vty), - PEER_FLAG_SEND_COMMUNITY); + snprintf(af_xpath, sizeof(af_xpath), FRR_BGP_AF_XPATH, + yang_afi_safi_value2identity(afi, safi)); + + if (peer_and_group_lookup_nb(vty, peer_str, base_xpath, + sizeof(base_xpath), af_xpath) + < 0) + return CMD_WARNING_CONFIG_FAILED; + + snprintf(std_xpath, sizeof(std_xpath), + "./%s/send-community/send-community", + bgp_afi_safi_get_container_str(afi, safi)); + + nb_cli_enqueue_change(vty, std_xpath, NB_OP_MODIFY, "false"); + + return nb_cli_apply_changes(vty, base_xpath); } ALIAS_HIDDEN(no_neighbor_send_community, no_neighbor_send_community_hidden_cmd, @@ -16966,18 +17019,36 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, } } else { if (peer->afc[afi][safi]) { - if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { - if (CHECK_FLAG(bgp->flags, - BGP_FLAG_NO_DEFAULT_IPV4)) { + if ((afi == AFI_IP || afi == AFI_IP6) + && safi == SAFI_UNICAST) { + if (afi == AFI_IP + && CHECK_FLAG(bgp->flags, + BGP_FLAG_NO_DEFAULT_IPV4)) { + vty_out(vty, " neighbor %s activate\n", + addr); + } else if (afi == AFI_IP6 + && !CHECK_FLAG( + bgp->flags, + BGP_FLAG_DEFAULT_IPV6)) { vty_out(vty, " neighbor %s activate\n", addr); } - } else + } else { vty_out(vty, " neighbor %s activate\n", addr); + } } else { - if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { - if (!CHECK_FLAG(bgp->flags, - BGP_FLAG_NO_DEFAULT_IPV4)) { + if ((afi == AFI_IP || afi == AFI_IP6) + && safi == SAFI_UNICAST) { + if (afi == AFI_IP + && !CHECK_FLAG(bgp->flags, + BGP_FLAG_NO_DEFAULT_IPV4)) { + vty_out(vty, + " no neighbor %s activate\n", + addr); + } else if (afi == AFI_IP6 + && CHECK_FLAG( + bgp->flags, + BGP_FLAG_DEFAULT_IPV6)) { vty_out(vty, " no neighbor %s activate\n", addr); @@ -17411,6 +17482,10 @@ int bgp_config_write(struct vty *vty) if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4)) vty_out(vty, " no bgp default ipv4-unicast\n"); + /* BGP default ipv6-unicast. */ + if (CHECK_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6)) + vty_out(vty, " bgp default ipv6-unicast\n"); + /* BGP default local-preference. */ if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF) vty_out(vty, " bgp default local-preference %u\n", @@ -18081,6 +18156,10 @@ void bgp_vty_init(void) install_element(BGP_NODE, &no_bgp_default_ipv4_unicast_cmd); install_element(BGP_NODE, &bgp_default_ipv4_unicast_cmd); + /* "no bgp default ipv6-unicast" commands. */ + install_element(BGP_NODE, &no_bgp_default_ipv6_unicast_cmd); + install_element(BGP_NODE, &bgp_default_ipv6_unicast_cmd); + /* "bgp network import-check" commands. */ install_element(BGP_NODE, &bgp_network_import_check_cmd); install_element(BGP_NODE, &bgp_network_import_check_exact_cmd); diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 85619dd074..251bdc3fe3 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -205,9 +205,9 @@ extern int peer_local_interface_cfg(struct bgp *bgp, const char *ip_str, const char *str, char *errmsg, size_t errmsg_len); extern int peer_conf_interface_create(struct bgp *bgp, const char *conf_if, - afi_t afi, safi_t safi, bool v6only, - const char *peer_group_name, int as_type, - as_t as, char *errmsg, size_t errmsg_len); + bool v6only, const char *peer_group_name, + int as_type, as_t as, char *errmsg, + size_t errmsg_len); extern int peer_flag_modify_nb(struct bgp *bgp, const char *ip_str, struct peer *peer, uint32_t flag, bool set, char *errmsg, size_t errmsg_len); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 10532f0915..4eb9229b55 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1468,8 +1468,10 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src) for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) { paf = peer_src->peer_af_array[afidx]; - if (paf != NULL) - peer_af_create(peer_dst, paf->afi, paf->safi); + if (paf != NULL) { + if (!peer_af_find(peer_dst, paf->afi, paf->safi)) + peer_af_create(peer_dst, paf->afi, paf->safi); + } } /* update-source apply */ @@ -1683,12 +1685,13 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp) */ struct peer *peer_create(union sockunion *su, const char *conf_if, struct bgp *bgp, as_t local_as, as_t remote_as, - int as_type, afi_t afi, safi_t safi, - struct peer_group *group) + int as_type, struct peer_group *group) { int active; struct peer *peer; char buf[SU_ADDRSTRLEN]; + afi_t afi; + safi_t safi; peer = peer_new(bgp); if (conf_if) { @@ -1747,9 +1750,23 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); - if (afi && safi) { - peer->afc[afi][safi] = 1; - peer_af_create(peer, afi, safi); + /* If address family is IPv4 and `bgp default ipv4-unicast` (default), + * then activate the neighbor for this AF. + * If address family is IPv6 and `bgp default ipv6-unicast` + * (non-default), then activate the neighbor for this AF. + */ + FOREACH_AFI_SAFI (afi, safi) { + if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) { + if ((afi == AFI_IP + && !CHECK_FLAG(bgp->flags, + BGP_FLAG_NO_DEFAULT_IPV4)) + || (afi == AFI_IP6 + && CHECK_FLAG(bgp->flags, + BGP_FLAG_DEFAULT_IPV6))) { + peer->afc[afi][safi] = 1; + peer_af_create(peer, afi, safi); + } + } } /* auto shutdown if configured */ @@ -1878,7 +1895,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified) /* If peer does not exist, create new one. If peer already exists, set AS number to the peer. */ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, - as_t *as, int as_type, afi_t afi, safi_t safi) + as_t *as, int as_type) { struct peer *peer; as_t local_as; @@ -1946,16 +1963,7 @@ int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if, else local_as = bgp->as; - /* If this is IPv4 unicast configuration and "no bgp default - ipv4-unicast" is specified. */ - - if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4) - && afi == AFI_IP && safi == SAFI_UNICAST) - peer_create(su, conf_if, bgp, local_as, *as, as_type, 0, - 0, NULL); - else - peer_create(su, conf_if, bgp, local_as, *as, as_type, - afi, safi, NULL); + peer_create(su, conf_if, bgp, local_as, *as, as_type, NULL); } return 0; @@ -2562,6 +2570,8 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name) group->conf = peer_new(bgp); if (!CHECK_FLAG(bgp->flags, BGP_FLAG_NO_DEFAULT_IPV4)) group->conf->afc[AFI_IP][SAFI_UNICAST] = 1; + if (CHECK_FLAG(bgp->flags, BGP_FLAG_DEFAULT_IPV6)) + group->conf->afc[AFI_IP6][SAFI_UNICAST] = 1; XFREE(MTYPE_BGP_PEER_HOST, group->conf->host); group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name); group->conf->group = group; @@ -2996,7 +3006,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, } peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, - group->conf->as_type, 0, 0, group); + group->conf->as_type, group); peer = peer_lock(peer); /* group->peer list reference */ listnode_add(group->peer, peer); @@ -3008,7 +3018,10 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, FOREACH_AFI_SAFI (afi, safi) { if (group->conf->afc[afi][safi]) { peer->afc[afi][safi] = 1; - peer_af_create(peer, afi, safi); + + if (!peer_af_find(peer, afi, safi)) + peer_af_create(peer, afi, safi); + peer_group2peer_config_copy_af(group, peer, afi, safi); } else if (peer->afc[afi][safi]) @@ -3807,7 +3820,7 @@ struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp, /* Create peer first; we've already checked group config is valid. */ peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as, - group->conf->as_type, 0, 0, group); + group->conf->as_type, group); if (!peer) return NULL; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 52c9491ff2..029019dd3c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -477,6 +477,7 @@ struct bgp { #define BGP_FLAG_SHUTDOWN (1 << 27) #define BGP_FLAG_SUPPRESS_FIB_PENDING (1 << 28) #define BGP_FLAG_SUPPRESS_DUPLICATES (1 << 29) +#define BGP_FLAG_DEFAULT_IPV6 (1 << 30) enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE] [BGP_GLOBAL_GR_EVENT_CMD]; @@ -1922,8 +1923,7 @@ extern bool peer_active(struct peer *); extern bool peer_active_nego(struct peer *); extern void bgp_recalculate_all_bestpaths(struct bgp *bgp); extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, - as_t, as_t, int, afi_t, safi_t, - struct peer_group *); + as_t, as_t, int, struct peer_group *); extern struct peer *peer_create_accept(struct bgp *); extern void peer_xfer_config(struct peer *dst, struct peer *src); extern char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json, @@ -1991,7 +1991,7 @@ extern bool bgp_update_delay_configured(struct bgp *); extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi); extern void peer_as_change(struct peer *, as_t, int); extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, - int, afi_t, safi_t); + int); extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int); extern int peer_delete(struct peer *peer); extern void peer_notify_unconfig(struct peer *peer); diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 3f8dafa09d..6c0a4306f4 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1087,6 +1087,9 @@ IPv6 Support be used in a setup with two upstreams where each of the upstreams should only receive either IPv4 or IPv6 annocuments. + Using the ``bgp default ipv6-unicast`` configuration, IPv6 unicast + address family is enabled by default for all new neighbors. + .. _bgp-route-aggregation: @@ -1576,6 +1579,12 @@ Configuring Peers on by default or not. This command defaults to on and is not displayed. The `no bgp default ipv4-unicast` form of the command is displayed. +.. clicmd:: bgp default ipv6-unicast + + This command allows the user to specify that v6 peering is turned + on by default or not. This command defaults to off and is not displayed. + The `bgp default ipv6-unicast` form of the command is displayed. + .. clicmd:: bgp default show-hostname This command shows the hostname of the peer in certain BGP commands diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 index d383ad5c6d..b7872d9870 100644 --- a/m4/ax_pthread.m4 +++ b/m4/ax_pthread.m4 @@ -219,7 +219,7 @@ for flag in $ax_pthread_flags; do # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h> - static void routine(void *a) { a = 0; } + static void routine(void *a) { if (a) a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); diff --git a/pathd/path_pcep_cli.c b/pathd/path_pcep_cli.c index 355790be8f..14404b1d08 100644 --- a/pathd/path_pcep_cli.c +++ b/pathd/path_pcep_cli.c @@ -1045,7 +1045,7 @@ static int path_pcep_cli_pcc_pcc_peer(struct vty *vty, const char *peer_name, XMALLOC(MTYPE_PCEP, sizeof(struct pcc_opts)); memcpy(&pcc_opts_copy->addr, &pce_opts_cli->pce_opts.config_opts.source_ip, - sizeof(struct pcc_opts)); + sizeof(pcc_opts_copy->addr)); pcc_opts_copy->msd = pcc_msd_g; pcc_opts_copy->port = pce_opts_cli->pce_opts.config_opts.source_port; if (pcep_ctrl_update_pcc_options(pcep_g->fpt, pcc_opts_copy)) { diff --git a/pceplib/pcep_msg_messages_encoding.c b/pceplib/pcep_msg_messages_encoding.c index 23ccef480c..7c8e1b3a1f 100644 --- a/pceplib/pcep_msg_messages_encoding.c +++ b/pceplib/pcep_msg_messages_encoding.c @@ -129,7 +129,7 @@ void pcep_encode_message(struct pcep_message *message, message_length += pcep_encode_object(node->data, versioning, message_buffer + message_length); - if (message_length > PCEP_MESSAGE_LENGTH) { + if (message_length >= PCEP_MESSAGE_LENGTH) { message->encoded_message = NULL; message->encoded_message_length = 0; return; @@ -295,6 +295,14 @@ struct pcep_message *pcep_decode_message(const uint8_t *msg_buf) msg_length = pcep_decode_msg_header(msg_buf, &msg_version, &msg_flags, &msg_type); + if (msg_length == 0) { + pcep_log(LOG_INFO, "%s: Discarding empty message", __func__); + return NULL; + } + if (msg_length >= PCEP_MESSAGE_LENGTH) { + pcep_log(LOG_INFO, "%s: Discarding message too big", __func__); + return NULL; + } struct pcep_message *msg = pceplib_calloc(PCEPLIB_MESSAGES, sizeof(struct pcep_message)); diff --git a/pceplib/pcep_msg_objects_encoding.c b/pceplib/pcep_msg_objects_encoding.c index d40b840869..c4089ba5ec 100644 --- a/pceplib/pcep_msg_objects_encoding.c +++ b/pceplib/pcep_msg_objects_encoding.c @@ -1668,7 +1668,7 @@ struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr, ipv6 = pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct in6_addr)); - decode_ipv6(uint32_ptr + LENGTH_4WORDS, ipv6); + decode_ipv6(uint32_ptr + 4, ipv6); dll_append(sr_subobj->nai_list, ipv6); read_count += LENGTH_8WORDS; @@ -1684,17 +1684,17 @@ struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr, struct in_addr *ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct in_addr)); - ipv4->s_addr = uint32_ptr[LENGTH_4WORDS]; + ipv4->s_addr = uint32_ptr[4]; dll_append(sr_subobj->nai_list, ipv4); ipv6 = pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct in6_addr)); - decode_ipv6(uint32_ptr + LENGTH_5WORDS, ipv6); + decode_ipv6(uint32_ptr + 5, ipv6); dll_append(sr_subobj->nai_list, ipv6); ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct in_addr)); - ipv4->s_addr = uint32_ptr[LENGTH_9WORDS]; + ipv4->s_addr = uint32_ptr[9]; dll_append(sr_subobj->nai_list, ipv4); read_count += LENGTH_10WORDS; diff --git a/pceplib/pcep_msg_tlvs.c b/pceplib/pcep_msg_tlvs.c index 890da9517f..9c84e71ee1 100644 --- a/pceplib/pcep_msg_tlvs.c +++ b/pceplib/pcep_msg_tlvs.c @@ -401,7 +401,7 @@ pcep_tlv_create_srpag_pol_name(const char *pol_name, uint16_t pol_name_length) (normalize_pcep_tlv_length(pol_name_length) > MAX_POLICY_NAME) ? MAX_POLICY_NAME : pol_name_length; - memcpy(tlv->name, pol_name, pol_name_length); + memcpy(tlv->name, pol_name, length); tlv->name_length = length; return tlv; @@ -456,7 +456,7 @@ pcep_tlv_create_tlv_arbitrary(const char *data, uint16_t data_length, uint16_t length = (data_length > MAX_ARBITRARY_SIZE) ? MAX_ARBITRARY_SIZE : data_length; - memcpy(tlv->data, data, data_length); + memcpy(tlv->data, data, length); tlv->data_length = length; tlv->arbitraty_type = tlv_id; diff --git a/pceplib/pcep_msg_tlvs_encoding.c b/pceplib/pcep_msg_tlvs_encoding.c index 3322663dc3..967f138143 100644 --- a/pceplib/pcep_msg_tlvs_encoding.c +++ b/pceplib/pcep_msg_tlvs_encoding.c @@ -1135,7 +1135,7 @@ struct pcep_object_tlv_header *pcep_decode_tlv_path_setup_type_capability( uint16_t buf_index = normalize_pcep_tlv_length( TLV_HEADER_LENGTH + LENGTH_1WORD + num_psts); while ((tlv->header.encoded_tlv_length - buf_index) > TLV_HEADER_LENGTH - && num_iterations++ > MAX_ITERATIONS) { + && num_iterations++ < MAX_ITERATIONS) { struct pcep_object_tlv_header *sub_tlv = pcep_decode_tlv(tlv_body_buf + buf_index); if (sub_tlv == NULL) { diff --git a/pceplib/pcep_msg_tools.c b/pceplib/pcep_msg_tools.c index 1d157ec3f5..e190d2a850 100644 --- a/pceplib/pcep_msg_tools.c +++ b/pceplib/pcep_msg_tools.c @@ -93,11 +93,11 @@ static const char *object_class_strs[] = {"NOT_IMPLEMENTED0", double_linked_list *pcep_msg_read(int sock_fd) { int ret; - uint8_t buffer[PCEP_MAX_SIZE] = {0}; + uint8_t buffer[PCEP_MESSAGE_LENGTH] = {0}; uint16_t buffer_read = 0; - ret = read(sock_fd, &buffer, PCEP_MAX_SIZE); + ret = read(sock_fd, &buffer, PCEP_MESSAGE_LENGTH); if (ret < 0) { pcep_log( @@ -114,13 +114,13 @@ double_linked_list *pcep_msg_read(int sock_fd) double_linked_list *msg_list = dll_initialize(); struct pcep_message *msg = NULL; - while ((ret - buffer_read) >= MESSAGE_HEADER_LENGTH) { + while (((uint16_t)ret - buffer_read) >= MESSAGE_HEADER_LENGTH) { /* Get the Message header, validate it, and return the msg * length */ - int32_t msg_hdr_length = + int32_t msg_length = pcep_decode_validate_msg_header(buffer + buffer_read); - if (msg_hdr_length < 0) { + if (msg_length < 0 || msg_length > PCEP_MESSAGE_LENGTH) { /* If the message header is invalid, we cant keep * reading since the length may be invalid */ pcep_log( @@ -130,17 +130,26 @@ double_linked_list *pcep_msg_read(int sock_fd) return msg_list; } - /* Check if the msg_hdr_length is longer than what was read, + /* Check if the msg_length is longer than what was read, * in which case, we need to read the rest of the message. */ - if ((ret - buffer_read) < msg_hdr_length) { - int read_len = (msg_hdr_length - (ret - buffer_read)); + if ((ret - buffer_read) < msg_length) { + int read_len = (msg_length - (ret - buffer_read)); int read_ret = 0; pcep_log( LOG_INFO, "%s: pcep_msg_read: Message not fully read! Trying to read %d bytes more, fd [%d]", __func__, read_len, sock_fd); - read_ret = read(sock_fd, &buffer[ret], read_len); + if (PCEP_MESSAGE_LENGTH - ret - buffer_read >= read_len ) + read_ret = + read(sock_fd, &buffer[ret], read_len); + else { + pcep_log( + LOG_ERR, + "%s: Trying to read size (%d) offset (%d) in a buff of size (%d)", + __func__, read_len, ret, PCEP_MESSAGE_LENGTH); + return msg_list; + } if (read_ret != read_len) { pcep_log( @@ -152,7 +161,7 @@ double_linked_list *pcep_msg_read(int sock_fd) } msg = pcep_decode_message(buffer + buffer_read); - buffer_read += msg_hdr_length; + buffer_read += msg_length; if (msg == NULL) { return msg_list; @@ -459,7 +468,12 @@ int pcep_msg_send(int sock_fd, struct pcep_message *msg) if (msg == NULL) { return 0; } + int msg_length = ntohs(msg->encoded_message_length); + if (msg_length > PCEP_MESSAGE_LENGTH) { + pcep_log(LOG_ERR, "%s: Not sended, size(% d) exceed max(% d) ", + __func__, msg_length, PCEP_MESSAGE_LENGTH); + return 0; + } - return write(sock_fd, msg->encoded_message, - ntohs(msg->encoded_message_length)); + return write(sock_fd, msg->encoded_message, msg_length); } diff --git a/pceplib/pcep_pcc.c b/pceplib/pcep_pcc.c index 2171f883cd..1a702a8b63 100644 --- a/pceplib/pcep_pcc.c +++ b/pceplib/pcep_pcc.c @@ -273,6 +273,7 @@ void send_pce_report_message(pcep_session *session) pcep_log(LOG_WARNING, "%s: send_pce_report_message SRP object was NULL", __func__); + dll_destroy_with_data(report_list); return; } dll_append(report_list, obj); @@ -313,6 +314,7 @@ void send_pce_report_message(pcep_session *session) pcep_log(LOG_WARNING, "%s: send_pce_report_message LSP object was NULL", __func__); + dll_destroy_with_data(report_list); return; } dll_append(report_list, obj); @@ -349,6 +351,7 @@ void send_pce_report_message(pcep_session *session) pcep_log(LOG_WARNING, "%s: send_pce_report_message ERO object was NULL", __func__); + dll_destroy_with_data(report_list); return; } dll_append(report_list, obj); diff --git a/pceplib/pcep_session_logic.c b/pceplib/pcep_session_logic.c index 5e4dae4900..52655914c6 100644 --- a/pceplib/pcep_session_logic.c +++ b/pceplib/pcep_session_logic.c @@ -61,7 +61,6 @@ static bool run_session_logic_common() memset(session_logic_handle_, 0, sizeof(pcep_session_logic_handle)); session_logic_handle_->active = true; - session_logic_handle_->session_logic_condition = false; session_logic_handle_->session_list = ordered_list_initialize(pointer_compare_function); session_logic_handle_->session_event_queue = queue_initialize(); @@ -91,6 +90,11 @@ static bool run_session_logic_common() return false; } + pthread_mutex_lock(&(session_logic_handle_->session_logic_mutex)); + session_logic_handle_->session_logic_condition = true; + pthread_cond_signal(&(session_logic_handle_->session_logic_cond_var)); + pthread_mutex_unlock(&(session_logic_handle_->session_logic_mutex)); + if (pthread_mutex_init(&(session_logic_handle_->session_list_mutex), NULL) != 0) { @@ -574,24 +578,20 @@ struct pcep_message *create_pcep_open(pcep_session *session) dll_append( tlv_list, pcep_tlv_create_stateful_pce_capability( + /* U flag */ session->pcc_config - .support_stateful_pce_lsp_update, /* U - flag - */ - session->pcc_config - .support_include_db_version, /* S flag - */ - session->pcc_config - .support_lsp_triggered_resync, /* T flag - */ - session->pcc_config - .support_lsp_delta_sync, /* D flag */ - session->pcc_config - .support_pce_triggered_initial_sync, /* F flag */ + .support_stateful_pce_lsp_update, + /* S flag */ + session->pcc_config.support_include_db_version, + /* I flag */ session->pcc_config - .support_pce_lsp_instantiation)); /* I - flag - */ + .support_pce_lsp_instantiation, + /* T flag */ + session->pcc_config.support_lsp_triggered_resync, + /* D flag */ + session->pcc_config.support_lsp_delta_sync, + /* F flag */ + session->pcc_config.support_pce_triggered_initial_sync)); } if (session->pcc_config.support_include_db_version) { diff --git a/pceplib/pcep_session_logic_loop.c b/pceplib/pcep_session_logic_loop.c index 5705ff2000..269aa1e07e 100644 --- a/pceplib/pcep_session_logic_loop.c +++ b/pceplib/pcep_session_logic_loop.c @@ -98,6 +98,7 @@ int session_logic_msg_ready_handler(void *data, int socket_fd) } else if (msg_list->num_entries == 0) { /* Invalid message received */ increment_unknown_message(session); + dll_destroy_with_data(msg_list); } else { /* Just logging the first of potentially several messages * received */ diff --git a/pceplib/pcep_session_logic_states.c b/pceplib/pcep_session_logic_states.c index e2c3c29591..3beceefad0 100644 --- a/pceplib/pcep_session_logic_states.c +++ b/pceplib/pcep_session_logic_states.c @@ -24,6 +24,7 @@ #include <stdbool.h> #include <stdio.h> #include <string.h> +#include <assert.h> #include "pcep_msg_encoding.h" #include "pcep_session_logic.h" @@ -461,6 +462,8 @@ void send_reconciled_pcep_open(pcep_session *session, struct pcep_object_open *open_obj = (struct pcep_object_open *)pcep_obj_get(open_msg->obj_list, PCEP_OBJ_CLASS_OPEN); + // open_msg can not have empty obj_list + assert(open_obj != NULL); if (error_open_obj->open_deadtimer != session->pce_config.dead_timer_seconds) { diff --git a/pceplib/pcep_socket_comm_loop.c b/pceplib/pcep_socket_comm_loop.c index 8346c93025..d58409c4f3 100644 --- a/pceplib/pcep_socket_comm_loop.c +++ b/pceplib/pcep_socket_comm_loop.c @@ -26,6 +26,7 @@ #include <stddef.h> #include <string.h> #include <unistd.h> +#include <assert.h> #include "pcep_socket_comm_internals.h" #include "pcep_socket_comm_loop.h" @@ -129,6 +130,9 @@ int build_fd_sets(pcep_socket_comm_handle *socket_comm_handle) comm_session = (pcep_socket_comm_session *)node->data; if (comm_session->socket_fd > max_fd) { max_fd = comm_session->socket_fd; + } else if (comm_session->socket_fd < 0) { + pcep_log(LOG_ERR, "%s: Negative fd", __func__); + assert(comm_session->socket_fd > 0); } /*pcep_log(LOG_DEBUG, ld] socket_comm::build_fdSets set @@ -147,6 +151,9 @@ int build_fd_sets(pcep_socket_comm_handle *socket_comm_handle) comm_session = (pcep_socket_comm_session *)node->data; if (comm_session->socket_fd > max_fd) { max_fd = comm_session->socket_fd; + } else if (comm_session->socket_fd < 0) { + pcep_log(LOG_ERR, "%s: Negative fd", __func__); + assert(comm_session->socket_fd > 0); } /*pcep_log(LOG_DEBUG, "%s: [%ld] socket_comm::build_fdSets set diff --git a/pceplib/test/pcep_msg_messages_test.c b/pceplib/test/pcep_msg_messages_test.c index 10b678bcec..b8984a42bc 100644 --- a/pceplib/test/pcep_msg_messages_test.c +++ b/pceplib/test/pcep_msg_messages_test.c @@ -111,7 +111,7 @@ void test_pcep_msg_create_request() /* Test IPv4 */ struct pcep_object_rp *rp_obj = pcep_obj_create_rp(0, false, false, false, false, 10, NULL); - struct in_addr src_addr, dst_addr; + struct in_addr src_addr={}, dst_addr={}; struct pcep_object_endpoints_ipv4 *ipv4_obj = pcep_obj_create_endpoint_ipv4(&src_addr, &dst_addr); message = pcep_msg_create_request(rp_obj, ipv4_obj, NULL); @@ -375,6 +375,10 @@ void test_pcep_msg_create_update() /* Should return NULL if obj_list is empty */ message = pcep_msg_create_update(obj_list); CU_ASSERT_PTR_NULL(message); + if (message != NULL) { + pcep_msg_free_message(message); + message = NULL; + } struct pcep_object_srp *srp = pcep_obj_create_srp(false, 100, NULL); struct pcep_object_lsp *lsp = @@ -390,6 +394,10 @@ void test_pcep_msg_create_update() CU_ASSERT_PTR_NULL(message); dll_append(obj_list, ero); + if (message != NULL) { + pcep_msg_free_message(message); + message = NULL; + } message = pcep_msg_create_update(obj_list); CU_ASSERT_PTR_NOT_NULL(message); pcep_encode_message(message, versioning); @@ -416,6 +424,10 @@ void test_pcep_msg_create_initiate() /* Should return NULL if obj_list is empty */ struct pcep_message *message = pcep_msg_create_initiate(NULL); CU_ASSERT_PTR_NULL(message); + if (message != NULL) { + pcep_msg_free_message(message); + message = NULL; + } struct pcep_object_srp *srp = pcep_obj_create_srp(false, 100, NULL); struct pcep_object_lsp *lsp = @@ -428,6 +440,10 @@ void test_pcep_msg_create_initiate() dll_append(obj_list, srp); message = pcep_msg_create_initiate(obj_list); CU_ASSERT_PTR_NULL(message); + if (message != NULL) { + pcep_msg_free_message(message); + message = NULL; + } dll_append(obj_list, lsp); dll_append(obj_list, ero); diff --git a/pceplib/test/pcep_msg_tlvs_test.c b/pceplib/test/pcep_msg_tlvs_test.c index 878e4d62af..6b650f6823 100644 --- a/pceplib/test/pcep_msg_tlvs_test.c +++ b/pceplib/test/pcep_msg_tlvs_test.c @@ -106,6 +106,10 @@ void test_pcep_tlv_create_speaker_entity_id() double_linked_list *list = dll_initialize(); tlv = pcep_tlv_create_speaker_entity_id(list); CU_ASSERT_PTR_NULL(tlv); + if (tlv != NULL) { + pceplib_free(PCEPLIB_INFRA, tlv); + tlv = NULL; + } uint32_t *speaker_entity = pceplib_malloc(PCEPLIB_MESSAGES, sizeof(uint32_t)); @@ -172,16 +176,28 @@ void test_pcep_tlv_create_path_setup_type_capability() double_linked_list *pst_list = dll_initialize(); tlv = pcep_tlv_create_path_setup_type_capability(pst_list, NULL); CU_ASSERT_PTR_NULL(tlv); + if (tlv != NULL) { + pcep_obj_free_tlv(&tlv->header); + tlv = NULL; + } /* Should still return NULL if pst_list is NULL */ double_linked_list *sub_tlv_list = dll_initialize(); tlv = pcep_tlv_create_path_setup_type_capability(NULL, sub_tlv_list); CU_ASSERT_PTR_NULL(tlv); + if (tlv != NULL) { + pcep_obj_free_tlv(&tlv->header); + tlv = NULL; + } /* Should still return NULL if pst_list is empty */ tlv = pcep_tlv_create_path_setup_type_capability(pst_list, sub_tlv_list); CU_ASSERT_PTR_NULL(tlv); + if (tlv != NULL) { + pcep_obj_free_tlv(&tlv->header); + tlv = NULL; + } /* Test only populating the pst list */ uint8_t *pst1 = pceplib_malloc(PCEPLIB_MESSAGES, 1); @@ -196,6 +212,10 @@ void test_pcep_tlv_create_path_setup_type_capability() tlv = pcep_tlv_create_path_setup_type_capability(pst_list, sub_tlv_list); CU_ASSERT_PTR_NOT_NULL(tlv); + if (tlv == NULL) { + CU_ASSERT_TRUE(tlv != NULL); + return; + } pcep_encode_tlv(&tlv->header, versioning, tlv_buf); CU_ASSERT_EQUAL(tlv->header.type, diff --git a/pceplib/test/pcep_msg_tools_test.c b/pceplib/test/pcep_msg_tools_test.c index a1260b1186..ff5fc62390 100644 --- a/pceplib/test/pcep_msg_tools_test.c +++ b/pceplib/test/pcep_msg_tools_test.c @@ -24,6 +24,9 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + #include <CUnit/CUnit.h> @@ -164,7 +167,15 @@ void pcep_tools_test_teardown(void) int convert_hexstrs_to_binary(const char *hexbyte_strs[], uint16_t hexbyte_strs_length) { - int fd = fileno(tmpfile()); + mode_t oldumask; + oldumask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); + /* Set umask before anything for security */ + umask(0027); + char tmpfile[] = "/tmp/pceplib_XXXXXX"; + int fd = mkstemp(tmpfile); + umask(oldumask); + if (fd == -1) + return -1; int i = 0; for (; i < hexbyte_strs_length; i++) { @@ -192,6 +203,10 @@ void test_pcep_msg_read_pcep_initiate() { int fd = convert_hexstrs_to_binary(pcep_initiate_hexbyte_strs, pcep_initiate_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -287,6 +302,10 @@ void test_pcep_msg_read_pcep_initiate2() { int fd = convert_hexstrs_to_binary(pcep_initiate2_hexbyte_strs, pcep_initiate2_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -370,6 +389,10 @@ void test_pcep_msg_read_pcep_open() { int fd = convert_hexstrs_to_binary(pcep_open_odl_hexbyte_strs, pcep_open_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -410,6 +433,10 @@ void test_pcep_msg_read_pcep_update() { int fd = convert_hexstrs_to_binary(pcep_update_hexbyte_strs, pcep_update_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -488,6 +515,10 @@ void test_pcep_msg_read_pcep_open_initiate() int fd = convert_hexstrs_to_binary( pcep_open_initiate_odl_hexbyte_strs, pcep_open_initiate_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 2); @@ -513,6 +544,10 @@ void test_pcep_msg_read_pcep_open_cisco_pce() int fd = convert_hexstrs_to_binary( pcep_open_cisco_pce_hexbyte_strs, pcep_open_cisco_pce_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -571,6 +606,10 @@ void test_pcep_msg_read_pcep_update_cisco_pce() int fd = convert_hexstrs_to_binary( pcep_update_cisco_pce_hexbyte_strs, pcep_update_cisco_pce_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -708,6 +747,10 @@ void test_pcep_msg_read_pcep_report_cisco_pcc() int fd = convert_hexstrs_to_binary( pcep_report_cisco_pcc_hexbyte_strs, pcep_report_cisco_pcc_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); @@ -863,6 +906,10 @@ void test_pcep_msg_read_pcep_initiate_cisco_pcc() int fd = convert_hexstrs_to_binary( pcep_initiate_cisco_pcc_hexbyte_strs, pcep_initiate_cisco_pcc_hexbyte_strs_length); + if(fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } double_linked_list *msg_list = pcep_msg_read(fd); CU_ASSERT_PTR_NOT_NULL(msg_list); CU_ASSERT_EQUAL(msg_list->num_entries, 1); diff --git a/pceplib/test/pcep_session_logic_loop_test.c b/pceplib/test/pcep_session_logic_loop_test.c index 38fabd4ccd..3a40f59bb9 100644 --- a/pceplib/test/pcep_session_logic_loop_test.c +++ b/pceplib/test/pcep_session_logic_loop_test.c @@ -25,6 +25,8 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> #include <CUnit/CUnit.h> @@ -70,7 +72,6 @@ void pcep_session_logic_loop_test_setup() PCEPLIB_INFRA, sizeof(pcep_session_logic_handle)); memset(session_logic_handle_, 0, sizeof(pcep_session_logic_handle)); session_logic_handle_->active = true; - session_logic_handle_->session_logic_condition = false; session_logic_handle_->session_list = ordered_list_initialize(pointer_compare_function); session_logic_handle_->session_event_queue = queue_initialize(); @@ -79,6 +80,11 @@ void pcep_session_logic_loop_test_setup() pthread_mutex_init(&(session_logic_handle_->session_logic_mutex), NULL); pthread_mutex_init(&(session_logic_handle_->session_list_mutex), NULL); + pthread_mutex_lock(&(session_logic_handle_->session_logic_mutex)); + session_logic_handle_->session_logic_condition = true; + pthread_cond_signal(&(session_logic_handle_->session_logic_cond_var)); + pthread_mutex_unlock(&(session_logic_handle_->session_logic_mutex)); + session_logic_event_queue_ = pceplib_malloc(PCEPLIB_INFRA, sizeof(pcep_event_queue)); memset(session_logic_event_queue_, 0, sizeof(pcep_event_queue)); @@ -128,7 +134,17 @@ void test_session_logic_msg_ready_handler() /* Read from an empty file should return 0, thus * session_logic_msg_ready_handler returns -1 */ - int fd = fileno(tmpfile()); + mode_t oldumask; + oldumask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); + /* Set umask before anything for security */ + umask(0027); + char tmpfile[] = "/tmp/pceplib_XXXXXX"; + int fd = mkstemp(tmpfile); + umask(oldumask); + if (fd == -1){ + CU_ASSERT_TRUE(fd>=0); + return; + } pcep_session session; memset(&session, 0, sizeof(pcep_session)); session.session_id = 100; diff --git a/pceplib/test/pcep_timers_event_loop_test.c b/pceplib/test/pcep_timers_event_loop_test.c index 9fcacaf0f2..ae63601df2 100644 --- a/pceplib/test/pcep_timers_event_loop_test.c +++ b/pceplib/test/pcep_timers_event_loop_test.c @@ -130,7 +130,9 @@ void test_walk_and_process_timers_timer_expired() timer->data = timer; // Set the timer to expire 10 seconds ago timer->expire_time = time(NULL) - 10; + pthread_mutex_lock(&test_timers_context->timer_list_lock); timer->timer_id = TEST_EVENT_LOOP_TIMER_ID; + pthread_mutex_unlock(&test_timers_context->timer_list_lock); ordered_list_add_node(test_timers_context->timer_list, timer); walk_and_process_timers(test_timers_context); diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py b/tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/__init__.py diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf new file mode 100644 index 0000000000..bf39152ea8 --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/bgpd.conf @@ -0,0 +1,3 @@ +! +router bgp 65001 +! diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf new file mode 100644 index 0000000000..697765168d --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r1/zebra.conf @@ -0,0 +1,7 @@ +! +interface r1-eth0 + ip address 192.168.255.1/24 +! +ip forwarding +! + diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf new file mode 100644 index 0000000000..abbd1b86fa --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/bgpd.conf @@ -0,0 +1,5 @@ +! +router bgp 65001 + no bgp default ipv4-unicast + bgp default ipv6-unicast +! diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf new file mode 100644 index 0000000000..606c17bec9 --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r2/zebra.conf @@ -0,0 +1,6 @@ +! +interface r2-eth0 + ip address 192.168.255.2/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf new file mode 100644 index 0000000000..a405c047ca --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/bgpd.conf @@ -0,0 +1,4 @@ +! +router bgp 65001 + bgp default ipv6-unicast +! diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf new file mode 100644 index 0000000000..e9fdfb70c5 --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/r3/zebra.conf @@ -0,0 +1,6 @@ +! +interface r3-eth0 + ip address 192.168.255.3/24 +! +ip forwarding +! diff --git a/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py b/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py new file mode 100644 index 0000000000..c1dbf0ebec --- /dev/null +++ b/tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2021 by +# Donatas Abraitis <donatas.abraitis@gmail.com> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +Test if `bgp default ipv4-unicast` and `bgp default ipv6-unicast` +commands work as expected. + +STEP 1: 'Check if neighbor 192.168.255.254 is enabled for ipv4 address-family only' +STEP 2: 'Check if neighbor 192.168.255.254 is enabled for ipv6 address-family only' +STEP 3: 'Check if neighbor 192.168.255.254 is enabled for ipv4 and ipv6 address-families' +""" + +import os +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from mininet.topo import Topo +from lib.common_config import step + + +class TemplateTopo(Topo): + def build(self, *_args, **_opts): + tgen = get_topogen(self) + + for routern in range(1, 5): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) + + +def setup_module(mod): + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_default_ipv4_ipv6_unicast(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + step("Check if neighbor 192.168.255.254 is enabled for ipv4 address-family only") + + def _bgp_neighbor_ipv4_af_only(): + tgen.gears["r1"].vtysh_cmd( + "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external" + ) + + output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp summary json")) + + if "ipv4Unicast" in output and "ipv6Unicast" not in output: + return True + return False + + assert _bgp_neighbor_ipv4_af_only() == True + + step("Check if neighbor 192.168.255.254 is enabled for ipv6 address-family only") + + def _bgp_neighbor_ipv6_af_only(): + tgen.gears["r2"].vtysh_cmd( + "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external" + ) + + output = json.loads(tgen.gears["r2"].vtysh_cmd("show bgp summary json")) + + if "ipv4Unicast" not in output and "ipv6Unicast" in output: + return True + return False + + assert _bgp_neighbor_ipv6_af_only() == True + + step( + "Check if neighbor 192.168.255.254 is enabled for ipv4 and ipv6 address-families" + ) + + def _bgp_neighbor_ipv4_and_ipv6_af(): + tgen.gears["r3"].vtysh_cmd( + "conf t\nrouter bgp\nneighbor 192.168.255.254 remote-as external" + ) + + output = json.loads(tgen.gears["r3"].vtysh_cmd("show bgp summary json")) + + if "ipv4Unicast" in output and "ipv6Unicast" in output: + return True + return False + + assert _bgp_neighbor_ipv4_and_ipv6_af() == True + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index 55b11dab3c..867831e114 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -43,6 +43,7 @@ from lib.common_config import ( run_frr_cmd, FRRCFG_FILE, retry, + get_ipv6_linklocal_address ) LOGDIR = "/tmp/topotests/" @@ -446,7 +447,7 @@ def __create_bgp_unicast_neighbor( cmd = "redistribute {}".format(redistribute["redist_type"]) redist_attr = redistribute.setdefault("attribute", None) if redist_attr: - if isinstance(redist_attr, dict): + if type(redist_attr) is dict: for key, value in redist_attr.items(): cmd = "{} {} {}".format(cmd, key, value) else: @@ -528,7 +529,7 @@ def __create_l2vpn_evpn_address_family( if advertise_data: for address_type, unicast_type in advertise_data.items(): - if isinstance(unicast_type, dict): + if type(unicast_type) is dict: for key, value in unicast_type.items(): cmd = "advertise {} {}".format(address_type, key) @@ -555,7 +556,7 @@ def __create_l2vpn_evpn_address_family( "ipv4" ].split("/")[0] - if isinstance(action, dict): + if type(action) is dict: next_hop_self = action.setdefault("next_hop_self", None) route_maps = action.setdefault("route_maps", {}) @@ -977,10 +978,6 @@ def modify_bgp_config_when_bgpd_down(tgen, topo, input_dict): router_list[router].run(cmd) except Exception as e: - # handle any exception - logger.error("Error %s occured. Arguments %s.", e.message, e.args) - - # Traceback errormsg = traceback.format_exc() logger.error(errormsg) return errormsg @@ -1085,10 +1082,10 @@ def verify_bgp_convergence(tgen, topo, dut=None): logger.debug("Entering lib API: verify_bgp_convergence()") for router, rnode in tgen.routers().items(): - if "bgp" not in topo["routers"][router]: + if dut is not None and dut != router: continue - if dut is not None and dut != router: + if "bgp" not in topo["routers"][router]: continue logger.info("Verifying BGP Convergence on router %s:", router) @@ -1114,59 +1111,7 @@ def verify_bgp_convergence(tgen, topo, dut=None): # To find neighbor ip type bgp_addr_type = bgp_data["address_family"] - if "l2vpn" in bgp_addr_type: - total_evpn_peer = 0 - - if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]: - continue - - bgp_neighbors = bgp_addr_type["l2vpn"]["evpn"]["neighbor"] - total_evpn_peer += len(bgp_neighbors) - - no_of_evpn_peer = 0 - for bgp_neighbor, peer_data in bgp_neighbors.items(): - for _addr_type, dest_link_dict in peer_data.items(): - data = topo["routers"][bgp_neighbor]["links"] - for dest_link in dest_link_dict.keys(): - if dest_link in data: - peer_details = peer_data[_addr_type][dest_link] - - neighbor_ip = data[dest_link][_addr_type].split("/")[0] - nh_state = None - - if ( - "ipv4Unicast" in show_bgp_json[vrf] - or "ipv6Unicast" in show_bgp_json[vrf] - ): - errormsg = ( - "[DUT: %s] VRF: %s, " - "ipv4Unicast/ipv6Unicast" - " address-family present" - " under l2vpn" % (router, vrf) - ) - return errormsg - - l2VpnEvpn_data = show_bgp_json[vrf]["l2VpnEvpn"][ - "peers" - ] - nh_state = l2VpnEvpn_data[neighbor_ip]["state"] - - if nh_state == "Established": - no_of_evpn_peer += 1 - - if no_of_evpn_peer == total_evpn_peer: - logger.info( - "[DUT: %s] VRF: %s, BGP is Converged for " "epvn peers", - router, - vrf, - ) - else: - errormsg = ( - "[DUT: %s] VRF: %s, BGP is not converged " - "for evpn peers" % (router, vrf) - ) - return errormsg - else: + if "ipv4" in bgp_addr_type or "ipv6" in bgp_addr_type: for addr_type in bgp_addr_type.keys(): if not check_address_types(addr_type): continue @@ -1216,32 +1161,102 @@ def verify_bgp_convergence(tgen, topo, dut=None): nh_state = None if addr_type == "ipv4": - ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][ - "peers" - ] - nh_state = ipv4_data[neighbor_ip]["state"] + if "ipv4Unicast" in show_bgp_json[vrf]: + ipv4_data = show_bgp_json[vrf]["ipv4Unicast"][ + "peers" + ] + nh_state = ipv4_data[neighbor_ip]["state"] else: - ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][ - "peers" - ] - nh_state = ipv6_data[neighbor_ip]["state"] - + if "ipv6Unicast" in show_bgp_json[vrf]: + ipv6_data = show_bgp_json[vrf]["ipv6Unicast"][ + "peers" + ] + nh_state = ipv6_data[neighbor_ip]["state"] if nh_state == "Established": no_of_peer += 1 - if no_of_peer == total_peer: - logger.info( - "[DUT: %s] VRF: %s, BGP is Converged for %s address-family", - router, - vrf, - addr_type, - ) + if "l2vpn" in bgp_addr_type: + if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]: + if no_of_peer == total_peer: + logger.info( + "[DUT: %s] VRF: %s, BGP is Converged for %s address-family", + router, + vrf, + addr_type, + ) + else: + errormsg = ( + "[DUT: %s] VRF: %s, BGP is not converged for %s address-family" + % (router, vrf, addr_type) + ) + return errormsg else: - errormsg = ( - "[DUT: %s] VRF: %s, BGP is not converged for %s address-family" - % (router, vrf, addr_type) - ) - return errormsg + if no_of_peer == total_peer: + logger.info( + "[DUT: %s] VRF: %s, BGP is Converged for %s address-family", + router, + vrf, + addr_type, + ) + else: + errormsg = ( + "[DUT: %s] VRF: %s, BGP is not converged for %s address-family" + % (router, vrf, addr_type) + ) + return errormsg + + if "l2vpn" in bgp_addr_type: + total_evpn_peer = 0 + + if "neighbor" not in bgp_addr_type["l2vpn"]["evpn"]: + continue + + bgp_neighbors = bgp_addr_type["l2vpn"]["evpn"]["neighbor"] + total_evpn_peer += len(bgp_neighbors) + + no_of_evpn_peer = 0 + for bgp_neighbor, peer_data in bgp_neighbors.items(): + for _addr_type, dest_link_dict in peer_data.items(): + data = topo["routers"][bgp_neighbor]["links"] + for dest_link in dest_link_dict.keys(): + if dest_link in data: + peer_details = peer_data[_addr_type][dest_link] + + neighbor_ip = data[dest_link][_addr_type].split("/")[0] + nh_state = None + + if ( + "ipv4Unicast" in show_bgp_json[vrf] + or "ipv6Unicast" in show_bgp_json[vrf] + ): + errormsg = ( + "[DUT: %s] VRF: %s, " + "ipv4Unicast/ipv6Unicast" + " address-family present" + " under l2vpn" % (router, vrf) + ) + return errormsg + + l2VpnEvpn_data = show_bgp_json[vrf]["l2VpnEvpn"][ + "peers" + ] + nh_state = l2VpnEvpn_data[neighbor_ip]["state"] + + if nh_state == "Established": + no_of_evpn_peer += 1 + + if no_of_evpn_peer == total_evpn_peer: + logger.info( + "[DUT: %s] VRF: %s, BGP is Converged for " "epvn peers", + router, + vrf, + ) + else: + errormsg = ( + "[DUT: %s] VRF: %s, BGP is not converged " + "for evpn peers" % (router, vrf) + ) + return errormsg logger.debug("Exiting API: verify_bgp_convergence()") return True @@ -1400,10 +1415,6 @@ def modify_as_number(tgen, topo, input_dict): create_router_bgp(tgen, new_topo) except Exception as e: - # handle any exception - logger.error("Error %s occured. Arguments %s.", e.message, e.args) - - # Traceback errormsg = traceback.format_exc() logger.error(errormsg) return errormsg @@ -2621,7 +2632,7 @@ def verify_bgp_rib( found_routes.append(st_rt) if next_hop and multi_nh and st_found: - if not isinstance(next_hop, list): + if type(next_hop) is not list: next_hop = [next_hop] list1 = next_hop @@ -2661,7 +2672,7 @@ def verify_bgp_rib( nh_found = True elif next_hop and multi_nh is None: - if not isinstance(next_hop, list): + if type(next_hop) is not list: next_hop = [next_hop] list1 = next_hop found_hops = [ @@ -4092,7 +4103,7 @@ def verify_attributes_for_evpn_routes( errormsg = ( "[DUT: %s] RD: %s, Route : %s " "is not present in cli json " - "output " % (dut, route) + "output " % (dut, _rd, route) ) return errormsg @@ -4170,7 +4181,7 @@ def verify_evpn_routes( return errormsg for key, route_data_json in evpn_value_json.items(): - if isinstance(route_data_json, dict): + if type(route_data_json) is dict: rd_keys += 1 if prefix not in route_data_json: missing_routes[key] = prefix @@ -4184,7 +4195,7 @@ def verify_evpn_routes( return errormsg for key, route_data_json in evpn_value_json.items(): - if isinstance(route_data_json, dict): + if type(route_data_json) is dict: if prefix not in route_data_json: continue diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index 9174389bea..a4c98924b6 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -1373,13 +1373,13 @@ def generate_ips(network, no_of_ips): if start_ip == "0.0.0.0" and mask == 0 and no_of_ips == 1: ipaddress_list.append("{}/{}".format(start_ip, mask)) return ipaddress_list - start_ip = ipaddress.IPv4Address(unicode(start_ip)) + start_ip = ipaddress.IPv4Address(frr_unicode(start_ip)) step = 2 ** (32 - mask) elif addr_type == "ipv6": if start_ip == "0::0" and mask == 0 and no_of_ips == 1: ipaddress_list.append("{}/{}".format(start_ip, mask)) return ipaddress_list - start_ip = ipaddress.IPv6Address(unicode(start_ip)) + start_ip = ipaddress.IPv6Address(frr_unicode(start_ip)) step = 2 ** (128 - mask) else: return [] @@ -1480,10 +1480,6 @@ def interface_status(tgen, topo, input_dict): load_config_to_router(tgen, router) except Exception as e: - # handle any exception - logger.error("Error %s occured. Arguments %s.", e.message, e.args) - - # Traceback errormsg = traceback.format_exc() logger.error(errormsg) return errormsg @@ -2442,51 +2438,6 @@ def shutdown_bringup_interface(tgen, dut, intf_name, ifaceaction=False): interface_set_status(router_list[dut], intf_name, ifaceaction) -def stop_router(tgen, router): - """ - Router's current config would be saved to /tmp/topotest/<suite>/<router> - for each daemon and router and its daemons would be stopped. - - * `tgen` : topogen object - * `router`: Device under test - """ - - router_list = tgen.routers() - - # Saving router config to /etc/frr, which will be loaded to router - # when it starts - router_list[router].vtysh_cmd("write memory") - - # Stop router - router_list[router].stop() - - -def start_router(tgen, router): - """ - Router will be started and config would be loaded from - /tmp/topotest/<suite>/<router> for each daemon - - * `tgen` : topogen object - * `router`: Device under test - """ - - logger.debug("Entering lib API: start_router") - - try: - router_list = tgen.routers() - - # Router and its daemons would be started and config would - # be loaded to router for each daemon from /etc/frr - router_list[router].start() - - except Exception as e: - errormsg = traceback.format_exc() - logger.error(errormsg) - return errormsg - - logger.debug("Exiting lib API: start_router()") - - def addKernelRoute( tgen, router, intf, group_addr_range, next_hop=None, src=None, del_action=None ): @@ -3754,6 +3705,43 @@ def verify_bgp_community(tgen, addr_type, router, network, input_dict=None): return True +def get_ipv6_linklocal_address(topo, node, intf): + """ + API to get the link local ipv6 address of a perticular interface + + Parameters + ---------- + * `node`: node on which link local ip to be fetched. + * `intf` : interface for which link local ip needs to be returned. + * `topo` : base topo + + Usage + ----- + result = get_ipv6_linklocal_address(topo, 'r1', 'r2') + + Returns link local ip of interface between r1 and r2. + + Returns + ------- + 1) link local ipv6 address from the interface + 2) errormsg - when link local ip not found + """ + tgen = get_topogen() + ext_nh = tgen.net[node].get_ipv6_linklocal() + req_nh = topo[node]['links'][intf]['interface'] + llip = None + for llips in ext_nh: + if llips[0] == req_nh: + llip = llips[1] + logger.info("Link local ip found = %s", llip) + return llip + + errormsg = "Failed: Link local ip not found on router {}, "\ + "interface {}".format(node, intf) + + return errormsg + + def verify_create_community_list(tgen, input_dict): """ API is to verify if large community list is created for any given DUT in |
