From 35cadacd2bb9383686753731e31bd7e145fb2506 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 06:24:32 +0200 Subject: Merging upstream version 10.0. Signed-off-by: Daniel Baumann --- ospf6d/ospf6_area.c | 4 +- ospf6d/ospf6_asbr.c | 7 +- ospf6d/ospf6_auth_trailer.c | 125 +++++-- ospf6d/ospf6_auth_trailer.h | 9 +- ospf6d/ospf6_gr.c | 27 +- ospf6d/ospf6_interface.c | 871 ++++++++++++++++++++++---------------------- ospf6d/ospf6_interface.h | 54 ++- ospf6d/ospf6_intra.c | 6 +- ospf6d/ospf6_main.c | 44 ++- ospf6d/ospf6_message.c | 103 +++++- ospf6d/ospf6_message.h | 5 + ospf6d/ospf6_neighbor.c | 567 ++++++++++++++++++++-------- ospf6d/ospf6_neighbor.h | 20 + ospf6d/ospf6_route.c | 6 +- ospf6d/ospf6_route.h | 2 +- ospf6d/ospf6_snmp.c | 7 +- ospf6d/ospf6_top.c | 170 +-------- ospf6d/ospf6_top.h | 2 + ospf6d/ospf6_zebra.c | 28 +- ospf6d/subdir.am | 2 + 20 files changed, 1175 insertions(+), 884 deletions(-) (limited to 'ospf6d') diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 69c711b..cf5479e 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -731,7 +731,7 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6) DEFUN (area_filter_list, area_filter_list_cmd, - "area filter-list prefix PREFIXLIST_NAME ", + "area filter-list prefix PREFIXLIST6_NAME ", "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" "OSPF6 area ID as a decimal value\n" @@ -774,7 +774,7 @@ DEFUN (area_filter_list, DEFUN (no_area_filter_list, no_area_filter_list_cmd, - "no area filter-list prefix PREFIXLIST_NAME ", + "no area filter-list prefix PREFIXLIST6_NAME ", NO_STR "OSPF6 area parameters\n" "OSPF6 area ID in IP address format\n" diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 99c3e16..d1c2b8b 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -481,7 +481,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, static int ospf6_ase_forward_address_check(struct ospf6 *ospf6, struct in6_addr *fwd_addr) { - struct listnode *anode, *node, *cnode; + struct listnode *anode, *node; struct ospf6_interface *oi; struct ospf6_area *oa; struct interface *ifp; @@ -494,7 +494,7 @@ static int ospf6_ase_forward_address_check(struct ospf6 *ospf6, continue; ifp = oi->interface; - for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { + frr_each (if_connected, ifp->connected, c) { if (IPV6_ADDR_SAME(&c->address->u.prefix6, fwd_addr)) return 0; @@ -1407,12 +1407,11 @@ static void ospf6_external_lsa_fwd_addr_set(struct ospf6 *ospf6, FOR_ALL_INTERFACES (vrf, ifp) { struct ospf6_interface *oi = ifp->info; struct connected *connected; - struct listnode *node; if (!oi || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) continue; - FOR_ALL_INTERFACES_ADDRESSES (ifp, connected, node) { + frr_each (if_connected, ifp->connected, connected) { if (connected->address->family != AF_INET6) continue; if (IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6)) diff --git a/ospf6d/ospf6_auth_trailer.c b/ospf6d/ospf6_auth_trailer.c index 10e0092..8d9eff4 100644 --- a/ospf6d/ospf6_auth_trailer.c +++ b/ospf6d/ospf6_auth_trailer.c @@ -4,6 +4,13 @@ */ #include "zebra.h" +#include + +#ifdef CRYPTO_OPENSSL +#include +#include +#endif + #include "config.h" #include "memory.h" #include "ospf6d.h" @@ -23,9 +30,13 @@ #include "ospf6_zebra.h" #include "lib/keychain.h" +#define OSPF6D_COMPAT_AUTHSEQ_NAME "%s/ospf6d-at-seq-no.dat", frr_runstatedir + unsigned char conf_debug_ospf6_auth[2]; DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor"); +static void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6); + /*Apad is the hexadecimal value 0x878FE1F3. */ const uint8_t ospf6_hash_apad_max[KEYCHAIN_MAX_HASH_SIZE] = { 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, @@ -855,23 +866,11 @@ void install_element_ospf6_clear_intf_auth(void) install_element(ENABLE_NODE, &clear_ipv6_ospf6_intf_auth_cmd); } -enum ospf6_auth_err ospf6_auth_nvm_file_exist(void) -{ - struct stat buffer; - int exist; - - exist = stat(OSPF6_AUTH_SEQ_NUM_FILE, &buffer); - if (exist == 0) - return OSPF6_AUTH_FILE_EXIST; - else - return OSPF6_AUTH_FILE_DO_NOT_EXIST; -} - /* * Record in non-volatile memory the given ospf6 process, * authentication trailer higher order sequence number. */ -void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6) +static void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6) { const char *inst_name; json_object *json; @@ -883,9 +882,7 @@ void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6) inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; - json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -905,49 +902,82 @@ void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6) */ json_object_int_add(json_instance, "sequence_number", ospf6->seqnum_h); - json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json, - JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } /* * Delete authentication sequence number for a given OSPF6 process * from non-volatile memory. */ -void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6) +__attribute__((unused)) static void +ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6) { const char *inst_name; json_object *json; json_object *json_instances; + json_object *json_instance; zlog_err("Higher order sequence number delete for %s process", ospf6->name); inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; - json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { - json_instances = json_object_new_object(); - json_object_object_add(json, "instances", json_instances); + json_object_put(json); + return; + } + + json_object_object_get_ex(json_instances, inst_name, &json_instance); + if (json_instance) { + json_object_put(json); + return; } - json_object_object_del(json_instances, inst_name); + json_object_object_del(json_instance, "sequence_number"); - json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json, - JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } +static struct json_object *ospf6_auth_seqno_compat_read(const char *inst_name) +{ + /* try legacy location */ + char compat_path[512]; + json_object *json; + json_object *json_instances = NULL; + json_object *json_instance = NULL; + json_object *json_seqnum = NULL; + + snprintf(compat_path, sizeof(compat_path), OSPF6D_COMPAT_AUTHSEQ_NAME); + json = json_object_from_file(compat_path); + + if (json) + json_object_object_get_ex(json, "instances", &json_instances); + if (json_instances) + json_object_object_get_ex(json_instances, inst_name, + &json_instance); + if (json_instance) + json_object_object_get_ex(json_instance, "sequence_number", + &json_seqnum); + if (json_seqnum) + /* => free the file-level object and still return this */ + json_seqnum = json_object_get(json_seqnum); + + if (json) { + json_object_free(json); + unlink(compat_path); + } + return json_seqnum; +} + /* * Fetch from non-volatile memory the stored ospf6 process * authentication sequence number. */ -void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6) +static void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6) { const char *inst_name; json_object *json; @@ -957,9 +987,7 @@ void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6) inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; - json = json_object_from_file((char *)OSPF6_AUTH_SEQ_NUM_FILE); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -976,13 +1004,34 @@ void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6) json_object_object_get_ex(json_instance, "sequence_number", &json_seqnum); - ospf6->seqnum_h = json_object_get_int(json_seqnum); + + if (json_seqnum) + /* cf. reference taken in compat_read above */ + json_seqnum = json_object_get(json_seqnum); + else + json_seqnum = ospf6_auth_seqno_compat_read(inst_name); + + ospf6->seqnum_l = 0; + if (json_seqnum) { + ospf6->seqnum_h = json_object_get_int(json_seqnum); + ospf6->seqnum_h += 1; + } else { + ospf6->seqnum_h = 0; + } + + if (json_seqnum) + json_object_put(json_seqnum); zlog_err("Higher order sequence number %d read for %s process %s", ospf6->seqnum_h, ospf6->name, strerror(errno)); - json_object_object_del(json_instances, inst_name); - json_object_to_file_ext((char *)OSPF6_AUTH_SEQ_NUM_FILE, json, - JSON_C_TO_STRING_PRETTY); - json_object_free(json); + json_object_object_del(json_instance, "sequence_number"); + + frr_daemon_state_save(&json); +} + +void ospf6_auth_init(struct ospf6 *o) +{ + ospf6_auth_seqno_nvm_read(o); + ospf6_auth_seqno_nvm_update(o); } diff --git a/ospf6d/ospf6_auth_trailer.h b/ospf6d/ospf6_auth_trailer.h index 3f82a7b..9073ae4 100644 --- a/ospf6d/ospf6_auth_trailer.h +++ b/ospf6d/ospf6_auth_trailer.h @@ -48,10 +48,10 @@ enum ospf6_auth_err { OSPF6_AUTH_VALIDATE_SUCCESS = 0, OSPF6_AUTH_VALIDATE_FAILURE, OSPF6_AUTH_PROCESS_NORMAL, - OSPF6_AUTH_FILE_EXIST, - OSPF6_AUTH_FILE_DO_NOT_EXIST }; +void ospf6_auth_init(struct ospf6 *o); + void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length); void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length, unsigned int lls_len); @@ -73,8 +73,5 @@ void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi, void install_element_ospf6_debug_auth(void); int config_write_ospf6_debug_auth(struct vty *vty); void install_element_ospf6_clear_intf_auth(void); -enum ospf6_auth_err ospf6_auth_nvm_file_exist(void); -void ospf6_auth_seqno_nvm_update(struct ospf6 *ospf6); -void ospf6_auth_seqno_nvm_delete(struct ospf6 *ospf6); -void ospf6_auth_seqno_nvm_read(struct ospf6 *ospf6); + #endif /* __OSPF6_AUTH_TRAILER_H__ */ diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c index 69230e5..34cb970 100644 --- a/ospf6d/ospf6_gr.c +++ b/ospf6d/ospf6_gr.c @@ -561,9 +561,7 @@ static void ospf6_gr_nvm_update(struct ospf6 *ospf6, bool prepare) inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; - json = json_object_from_file((char *)OSPF6D_GR_STATE); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -591,9 +589,7 @@ static void ospf6_gr_nvm_update(struct ospf6 *ospf6, bool prepare) json_object_int_add(json_instance, "timestamp", time(NULL) + ospf6->gr_info.grace_period); - json_object_to_file_ext((char *)OSPF6D_GR_STATE, json, - JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } /* @@ -608,9 +604,7 @@ void ospf6_gr_nvm_delete(struct ospf6 *ospf6) inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; - json = json_object_from_file((char *)OSPF6D_GR_STATE); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -620,9 +614,7 @@ void ospf6_gr_nvm_delete(struct ospf6 *ospf6) json_object_object_del(json_instances, inst_name); - json_object_to_file_ext((char *)OSPF6D_GR_STATE, json, - JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } /* @@ -641,9 +633,7 @@ void ospf6_gr_nvm_read(struct ospf6 *ospf6) inst_name = ospf6->name ? ospf6->name : VRF_DEFAULT_NAME; - json = json_object_from_file((char *)OSPF6D_GR_STATE); - if (json == NULL) - json = json_object_new_object(); + json = frr_daemon_state_load(); json_object_object_get_ex(json, "instances", &json_instances); if (!json_instances) { @@ -687,11 +677,10 @@ void ospf6_gr_nvm_read(struct ospf6 *ospf6) ospf6->gr_info.grace_period); } - json_object_object_del(json_instances, inst_name); + json_object_object_del(json_instance, "gracePeriod"); + json_object_object_del(json_instance, "timestamp"); - json_object_to_file_ext((char *)OSPF6D_GR_STATE, json, - JSON_C_TO_STRING_PRETTY); - json_object_free(json); + frr_daemon_state_save(&json); } void ospf6_gr_unplanned_start_interface(struct ospf6_interface *oi) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index a79f993..b9dace2 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -49,8 +49,9 @@ DEFINE_HOOK(ospf6_interface_change, unsigned char conf_debug_ospf6_interface = 0; const char *const ospf6_interface_state_str[] = { - "None", "Down", "Loopback", "Waiting", "PointToPoint", - "DROther", "BDR", "DR", NULL}; + "None", "Down", "Loopback", "Waiting", "PointToPoint", + "PtMultipoint", "DROther", "BDR", "DR", NULL +}; int ospf6_interface_neighbor_count(struct ospf6_interface *oi) { @@ -83,8 +84,7 @@ struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex, } /* schedule routing table recalculation */ -static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa, - unsigned int reason) +static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa, unsigned int reason) { struct ospf6_interface *oi; @@ -227,9 +227,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp) iobuflen = ospf6_iobuf_size(ifp->mtu6); if (oi->ifmtu > iobuflen) { if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug( - "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", - ifp->name, iobuflen); + zlog_debug("Interface %s: IfMtu is adjusted to I/O buffer size: %d.", + ifp->name, iobuflen); oi->ifmtu = iobuflen; } @@ -242,8 +241,8 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp) oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove; oi->lsdb_self = ospf6_lsdb_create(oi); - oi->route_connected = - OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES); + oi->route_connected = OSPF6_ROUTE_TABLE_CREATE(INTERFACE, + CONNECTED_ROUTES); oi->route_connected->scope = oi; /* link both */ @@ -344,12 +343,11 @@ void ospf6_interface_disable(struct ospf6_interface *oi) static struct in6_addr * ospf6_interface_get_linklocal_address(struct interface *ifp) { - struct listnode *n; struct connected *c; struct in6_addr *l = (struct in6_addr *)NULL; /* for each connected address */ - for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { + frr_each (if_connected, ifp->connected, c) { /* if family not AF_INET6, ignore */ if (c->address->family != AF_INET6) continue; @@ -380,23 +378,21 @@ void ospf6_interface_state_update(struct interface *ifp) iobuflen = ospf6_iobuf_size(ifp->mtu6); if (oi->ifmtu > iobuflen) { if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug( - "Interface %s: IfMtu is adjusted to I/O buffer size: %d.", - ifp->name, iobuflen); + zlog_debug("Interface %s: IfMtu is adjusted to I/O buffer size: %d.", + ifp->name, iobuflen); oi->ifmtu = iobuflen; } } else if (oi->c_ifmtu > ifp->mtu6) { oi->ifmtu = ifp->mtu6; - zlog_warn( - "Configured mtu %u on %s overridden by kernel %u", - oi->c_ifmtu, ifp->name, ifp->mtu6); + zlog_warn("Configured mtu %u on %s overridden by kernel %u", + oi->c_ifmtu, ifp->name, ifp->mtu6); } else oi->ifmtu = oi->c_ifmtu; } - if (if_is_operative(ifp) - && (ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) + if (if_is_operative(ifp) && + (ospf6_interface_get_linklocal_address(oi->interface) || + if_is_loopback(oi->interface))) event_execute(master, interface_up, oi, 0, NULL); else event_execute(master, interface_down, oi, 0, NULL); @@ -407,9 +403,7 @@ void ospf6_interface_state_update(struct interface *ifp) void ospf6_interface_connected_route_update(struct interface *ifp) { struct ospf6_interface *oi; - struct ospf6_route *route; struct connected *c; - struct listnode *node, *nnode; struct in6_addr nh_addr; oi = (struct ospf6_interface *)ifp->info; @@ -429,7 +423,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp) /* update "route to advertise" interface route table */ ospf6_route_remove_all(oi->route_connected); - for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) { + frr_each (if_connected, ifp->connected, c) { if (c->address->family != AF_INET6) continue; @@ -453,14 +447,43 @@ void ospf6_interface_connected_route_update(struct interface *ifp) ret = prefix_list_apply(plist, (void *)c->address); if (ret == PREFIX_DENY) { if (IS_OSPF6_DEBUG_INTERFACE) - zlog_debug( - "%pFX on %s filtered by prefix-list %s ", - c->address, oi->interface->name, - oi->plist_name); + zlog_debug("%pFX on %s filtered by prefix-list %s ", + c->address, + oi->interface->name, + oi->plist_name); continue; } } + if (oi->state == OSPF6_INTERFACE_LOOPBACK || + oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT || + oi->state == OSPF6_INTERFACE_POINTTOPOINT) { + struct ospf6_route *la_route; + + la_route = ospf6_route_create(oi->area->ospf6); + la_route->prefix = *c->address; + la_route->prefix.prefixlen = 128; + la_route->prefix_options |= OSPF6_PREFIX_OPTION_LA; + + la_route->type = OSPF6_DEST_TYPE_NETWORK; + la_route->path.area_id = oi->area->area_id; + la_route->path.type = OSPF6_PATH_TYPE_INTRA; + la_route->path.cost = 0; + inet_pton(AF_INET6, "::1", &nh_addr); + ospf6_route_add_nexthop(la_route, oi->interface->ifindex, + &nh_addr); + ospf6_route_add(la_route, oi->route_connected); + } + + if (oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT && + !oi->p2xp_connected_pfx_include) + continue; + if (oi->state == OSPF6_INTERFACE_POINTTOPOINT && + oi->p2xp_connected_pfx_exclude) + continue; + + struct ospf6_route *route; + route = ospf6_route_create(oi->area->ospf6); memcpy(&route->prefix, c->address, sizeof(struct prefix)); apply_mask(&route->prefix); @@ -469,8 +492,7 @@ void ospf6_interface_connected_route_update(struct interface *ifp) route->path.type = OSPF6_PATH_TYPE_INTRA; route->path.cost = oi->cost; inet_pton(AF_INET6, "::1", &nh_addr); - ospf6_route_add_nexthop(route, oi->interface->ifindex, - &nh_addr); + ospf6_route_add_nexthop(route, oi->interface->ifindex, &nh_addr); ospf6_route_add(route, oi->route_connected); } @@ -506,17 +528,17 @@ static int ospf6_interface_state_change(uint8_t next_state, ospf6 = oi->area->ospf6; - if ((prev_state == OSPF6_INTERFACE_DR - || prev_state == OSPF6_INTERFACE_BDR) - && (next_state != OSPF6_INTERFACE_DR - && next_state != OSPF6_INTERFACE_BDR)) + if ((prev_state == OSPF6_INTERFACE_DR || + prev_state == OSPF6_INTERFACE_BDR) && + (next_state != OSPF6_INTERFACE_DR && + next_state != OSPF6_INTERFACE_BDR)) ospf6_sso(oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP, ospf6->fd); - if ((prev_state != OSPF6_INTERFACE_DR - && prev_state != OSPF6_INTERFACE_BDR) - && (next_state == OSPF6_INTERFACE_DR - || next_state == OSPF6_INTERFACE_BDR)) + if ((prev_state != OSPF6_INTERFACE_DR && + prev_state != OSPF6_INTERFACE_BDR) && + (next_state == OSPF6_INTERFACE_DR || + next_state == OSPF6_INTERFACE_BDR)) ospf6_sso(oi->interface->ifindex, &alldrouters6, IPV6_JOIN_GROUP, ospf6->fd); @@ -526,13 +548,17 @@ static int ospf6_interface_state_change(uint8_t next_state, OSPF6_NETWORK_LSA_EXECUTE(oi); OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); - } else if (prev_state == OSPF6_INTERFACE_DR - || next_state == OSPF6_INTERFACE_DR) { + } else if (prev_state == OSPF6_INTERFACE_DR || + next_state == OSPF6_INTERFACE_DR) { OSPF6_NETWORK_LSA_SCHEDULE(oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi); OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area); } + if (next_state == OSPF6_INTERFACE_POINTTOPOINT || + next_state == OSPF6_INTERFACE_POINTTOMULTIPOINT) + ospf6_if_p2xp_up(oi); + hook_call(ospf6_interface_change, oi, next_state, prev_state); return 0; @@ -547,8 +573,8 @@ static int ospf6_interface_state_change(uint8_t next_state, static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a, struct ospf6_neighbor *b) { - if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) - && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)) + if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) && + (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)) return NULL; else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id) return b; @@ -577,8 +603,8 @@ static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a, static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a, struct ospf6_neighbor *b) { - if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) - && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)) + if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) && + (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)) return NULL; else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id) return b; @@ -641,10 +667,10 @@ uint8_t dr_election(struct ospf6_interface *oi) drouter = bdrouter; /* the router itself is newly/no longer DR/BDR (4) */ - if ((drouter == &myself && myself.drouter != myself.router_id) - || (drouter != &myself && myself.drouter == myself.router_id) - || (bdrouter == &myself && myself.bdrouter != myself.router_id) - || (bdrouter != &myself && myself.bdrouter == myself.router_id)) { + if ((drouter == &myself && myself.drouter != myself.router_id) || + (drouter != &myself && myself.drouter == myself.router_id) || + (bdrouter == &myself && myself.bdrouter != myself.router_id) || + (bdrouter != &myself && myself.bdrouter == myself.router_id)) { myself.drouter = (drouter ? drouter->router_id : htonl(0)); myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0)); @@ -718,8 +744,8 @@ static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr) continue; sdl = (struct sockaddr_dl *)ifma->ifma_name; sin6 = (struct sockaddr_in6 *)ifma->ifma_addr; - if (sdl->sdl_index == ifindex - && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) { + if (sdl->sdl_index == ifindex && + memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) { found = true; break; } @@ -759,11 +785,10 @@ void interface_up(struct event *thread) } /* check interface has a link-local address */ - if (!(ospf6_interface_get_linklocal_address(oi->interface) - || if_is_loopback(oi->interface))) { - zlog_warn( - "Interface %s has no link local address, can't execute [InterfaceUp]", - oi->interface->name); + if (!(ospf6_interface_get_linklocal_address(oi->interface) || + if_is_loopback(oi->interface))) { + zlog_warn("Interface %s has no link local address, can't execute [InterfaceUp]", + oi->interface->name); return; } @@ -780,9 +805,8 @@ void interface_up(struct event *thread) /* If no area assigned, return */ if (oi->area == NULL) { - zlog_warn( - "%s: Not scheduling Hello for %s as there is no area assigned yet", - __func__, oi->interface->name); + zlog_warn("%s: Not scheduling Hello for %s as there is no area assigned yet", + __func__, oi->interface->name); return; } @@ -807,9 +831,8 @@ void interface_up(struct event *thread) * the interface actually left the group. */ if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) { - zlog_info( - "Interface %s is still in all routers group, rescheduling for SSO", - oi->interface->name); + zlog_info("Interface %s is still in all routers group, rescheduling for SSO", + oi->interface->name); event_add_timer(master, interface_up, oi, OSPF6_INTERFACE_SSO_RETRY_INT, &oi->thread_sso); return; @@ -820,12 +843,10 @@ void interface_up(struct event *thread) /* Join AllSPFRouters */ if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP, - ospf6->fd) - < 0) { + ospf6->fd) < 0) { if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) { - zlog_info( - "Scheduling %s for sso retry, trial count: %d", - oi->interface->name, oi->sso_try_cnt); + zlog_info("Scheduling %s for sso retry, trial count: %d", + oi->interface->name, oi->sso_try_cnt); event_add_timer(master, interface_up, oi, OSPF6_INTERFACE_SSO_RETRY_INT, &oi->thread_sso); @@ -838,8 +859,8 @@ void interface_up(struct event *thread) ospf6_interface_connected_route_update(oi->interface); /* Schedule Hello */ - if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) - && !if_is_loopback(oi->interface)) { + if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE) && + !if_is_loopback(oi->interface)) { event_add_timer(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); } @@ -849,6 +870,9 @@ void interface_up(struct event *thread) ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi); } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) { ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi); + } else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) { + ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOMULTIPOINT, + oi); } else if (oi->priority == 0) ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi); else { @@ -899,9 +923,8 @@ void neighbor_change(struct event *thread) zlog_debug("Interface Event %s: [NeighborChange]", oi->interface->name); - if (oi->state == OSPF6_INTERFACE_DROTHER - || oi->state == OSPF6_INTERFACE_BDR - || oi->state == OSPF6_INTERFACE_DR) + if (oi->state == OSPF6_INTERFACE_DROTHER || + oi->state == OSPF6_INTERFACE_BDR || oi->state == OSPF6_INTERFACE_DR) ospf6_interface_state_change(dr_election(oi), oi); } @@ -977,6 +1000,8 @@ static const char *ospf6_iftype_str(uint8_t iftype) return "BROADCAST"; case OSPF_IFTYPE_POINTOPOINT: return "POINTOPOINT"; + case OSPF_IFTYPE_POINTOMULTIPOINT: + return "POINTOMULTIPOINT"; } return "UNKNOWN"; } @@ -988,7 +1013,6 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, struct ospf6_interface *oi; struct connected *c; struct prefix *p; - struct listnode *i; char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32]; uint8_t default_iftype; struct timeval res, now; @@ -1035,7 +1059,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, if (use_json) { json_arr = json_object_new_array(); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) { + frr_each (if_connected, ifp->connected, c) { json_addr = json_object_new_object(); p = c->address; prefix2str(p, strbuf, sizeof(strbuf)); @@ -1067,7 +1091,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, } else { vty_out(vty, " Internet Address:\n"); - for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) { + frr_each (if_connected, ifp->connected, c) { p = c->address; prefix2str(p, strbuf, sizeof(strbuf)); switch (p->family) { @@ -1086,12 +1110,10 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, if (use_json) { if (oi->area) { - json_object_boolean_true_add(json_obj, - "attachedToArea"); + json_object_boolean_true_add(json_obj, "attachedToArea"); json_object_int_add(json_obj, "instanceId", oi->instance_id); - json_object_int_add(json_obj, "interfaceMtu", - oi->ifmtu); + json_object_int_add(json_obj, "interfaceMtu", oi->ifmtu); json_object_int_add(json_obj, "autoDetect", ifp->mtu6); json_object_string_add(json_obj, "mtuMismatchDetection", oi->mtu_ignore ? "disabled" @@ -1131,9 +1153,9 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, oi->dead_interval); json_object_int_add(json_obj, "timerIntervalsConfigRetransmit", oi->rxmt_interval); - json_object_boolean_add( - json_obj, "timerPassiveIface", - !!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)); + json_object_boolean_add(json_obj, "timerPassiveIface", + !!CHECK_FLAG(oi->flag, + OSPF6_INTERFACE_PASSIVE)); } else { vty_out(vty, " State %s, Transmit Delay %d sec, Priority %d\n", ospf6_interface_state_str[oi->state], oi->transdelay, @@ -1166,24 +1188,23 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, if (use_json) { timerclear(&res); if (event_is_scheduled(oi->thread_send_lsupdate)) - timersub(&oi->thread_send_lsupdate->u.sands, &now, - &res); + timersub(&oi->thread_send_lsupdate->u.sands, &now, &res); timerstring(&res, duration, sizeof(duration)); json_object_int_add(json_obj, "pendingLsaLsUpdateCount", oi->lsupdate_list->count); json_object_string_add(json_obj, "pendingLsaLsUpdateTime", duration); - json_object_string_add( - json_obj, "lsUpdateSendThread", - (event_is_scheduled(oi->thread_send_lsupdate) ? "on" - : "off")); + json_object_string_add(json_obj, "lsUpdateSendThread", + (event_is_scheduled( + oi->thread_send_lsupdate) + ? "on" + : "off")); json_arr = json_object_new_array(); for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) - json_object_array_add( - json_arr, json_object_new_string(lsa->name)); - json_object_object_add(json_obj, "pendingLsaLsUpdate", - json_arr); + json_object_array_add(json_arr, + json_object_new_string(lsa->name)); + json_object_object_add(json_obj, "pendingLsaLsUpdate", json_arr); timerclear(&res); if (event_is_scheduled(oi->thread_send_lsack)) @@ -1194,15 +1215,15 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, oi->lsack_list->count); json_object_string_add(json_obj, "pendingLsaLsAckTime", duration); - json_object_string_add( - json_obj, "lsAckSendThread", - (event_is_scheduled(oi->thread_send_lsack) ? "on" - : "off")); + json_object_string_add(json_obj, "lsAckSendThread", + (event_is_scheduled(oi->thread_send_lsack) + ? "on" + : "off")); json_arr = json_object_new_array(); for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) - json_object_array_add( - json_arr, json_object_new_string(lsa->name)); + json_object_array_add(json_arr, + json_object_new_string(lsa->name)); json_object_object_add(json_obj, "pendingLsaLsAck", json_arr); if (oi->gr.hello_delay.interval != 0) @@ -1211,8 +1232,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, } else { timerclear(&res); if (event_is_scheduled(oi->thread_send_lsupdate)) - timersub(&oi->thread_send_lsupdate->u.sands, &now, - &res); + timersub(&oi->thread_send_lsupdate->u.sands, &now, &res); timerstring(&res, duration, sizeof(duration)); vty_out(vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", @@ -1244,9 +1264,8 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, if (use_json) { struct json_object *json_bfd = json_object_new_object(); - json_object_int_add( - json_bfd, "detectMultiplier", - oi->bfd_config.detection_multiplier); + json_object_int_add(json_bfd, "detectMultiplier", + oi->bfd_config.detection_multiplier); json_object_int_add(json_bfd, "rxMinInterval", oi->bfd_config.min_rx); json_object_int_add(json_bfd, "txMinInterval", @@ -1269,8 +1288,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, OSPF6_AUTH_TRAILER_KEYCHAIN)) { json_object_string_add(json_auth, "authType", "keychain"); - json_object_string_add(json_auth, - "keychainName", + json_object_string_add(json_auth, "keychainName", oi->at_data.keychain); } else if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) @@ -1310,11 +1328,10 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp, /* Find the global address to be used as a forwarding address in NSSA LSA.*/ struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp) { - struct listnode *n; struct connected *c; /* for each connected address */ - for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) { + frr_each (if_connected, ifp->connected, c) { /* if family not AF_INET6, ignore */ if (c->address->family != AF_INET6) continue; @@ -1332,7 +1349,6 @@ static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id, int idx_ifname, int intf_idx, int json_idx, bool uj) { - struct vrf *vrf = vrf_lookup_by_id(vrf_id); struct interface *ifp; json_object *json; @@ -1462,18 +1478,15 @@ static int ospf6_interface_show_traffic(struct vty *vty, json_object_int_add(json_interface, "lsReqTx", oi->ls_req_out); json_object_int_add(json_interface, - "lsUpdateRx", - oi->ls_upd_in); - json_object_int_add(json_interface, - "lsUpdateTx", + "lsUpdateRx", oi->ls_upd_in); + json_object_int_add(json_interface, "lsUpdateTx", oi->ls_upd_out); json_object_int_add(json_interface, "lsAckRx", oi->ls_ack_in); json_object_int_add(json_interface, "lsAckTx", oi->ls_ack_out); - json_object_object_add(json, - oi->interface->name, + json_object_object_add(json, oi->interface->name, json_interface); } else vty_out(vty, @@ -1659,8 +1672,8 @@ DEFUN(show_ipv6_ospf6_interface_ifname_prefix, } oi = ifp->info; - if (oi == NULL - || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { + if (oi == NULL || + CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { vty_out(vty, "Interface %s not attached to area\n", argv[idx_ifname]->arg); @@ -1687,8 +1700,7 @@ DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, | []\ >] [json]", SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR - "All VRFs\n" INTERFACE_STR - "Display connected prefixes to advertise\n" + "All VRFs\n" INTERFACE_STR "Display connected prefixes to advertise\n" "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR "Display details of the prefixes\n" JSON_STR) @@ -1713,9 +1725,9 @@ DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, vrf = vrf_lookup_by_id(ospf6->vrf_id); FOR_ALL_INTERFACES (vrf, ifp) { oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL - || CHECK_FLAG(oi->flag, - OSPF6_INTERFACE_DISABLE)) + if (oi == NULL || + CHECK_FLAG(oi->flag, + OSPF6_INTERFACE_DISABLE)) continue; ospf6_route_table_show(vty, idx_prefix, argc, @@ -1790,14 +1802,11 @@ void ospf6_interface_stop(struct ospf6_interface *oi) } /* interface variable set command */ -DEFUN (ipv6_ospf6_area, - ipv6_ospf6_area_cmd, - "ipv6 ospf6 area ", - IP6_STR - OSPF6_STR - "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n") +DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd, + "ipv6 ospf6 area ", + IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1831,15 +1840,11 @@ DEFUN (ipv6_ospf6_area, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_area, - no_ipv6_ospf6_area_cmd, - "no ipv6 ospf6 area []", - NO_STR - IP6_STR - OSPF6_STR - "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n") +DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd, + "no ipv6 ospf6 area []", + NO_STR IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n" + "OSPF6 area ID in IPv4 address notation\n" + "OSPF6 area ID in decimal notation\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1859,14 +1864,9 @@ DEFUN (no_ipv6_ospf6_area, return CMD_SUCCESS; } -DEFUN (ipv6_ospf6_ifmtu, - ipv6_ospf6_ifmtu_cmd, - "ipv6 ospf6 ifmtu (1-65535)", - IP6_STR - OSPF6_STR - "Interface MTU\n" - "OSPFv3 Interface MTU\n" - ) +DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)", + IP6_STR OSPF6_STR "Interface MTU\n" + "OSPFv3 Interface MTU\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1915,15 +1915,10 @@ DEFUN (ipv6_ospf6_ifmtu, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_ifmtu, - no_ipv6_ospf6_ifmtu_cmd, - "no ipv6 ospf6 ifmtu [(1-65535)]", - NO_STR - IP6_STR - OSPF6_STR - "Interface MTU\n" - "OSPFv3 Interface MTU\n" - ) +DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd, + "no ipv6 ospf6 ifmtu [(1-65535)]", + NO_STR IP6_STR OSPF6_STR "Interface MTU\n" + "OSPFv3 Interface MTU\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -1961,13 +1956,9 @@ DEFUN (no_ipv6_ospf6_ifmtu, return CMD_SUCCESS; } -DEFUN (ipv6_ospf6_cost, - ipv6_ospf6_cost_cmd, - "ipv6 ospf6 cost (1-65535)", - IP6_STR - OSPF6_STR - "Interface cost\n" - "Outgoing metric of this interface\n") +DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)", + IP6_STR OSPF6_STR "Interface cost\n" + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -1998,14 +1989,10 @@ DEFUN (ipv6_ospf6_cost, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_cost, - no_ipv6_ospf6_cost_cmd, - "no ipv6 ospf6 cost [(1-65535)]", - NO_STR - IP6_STR - OSPF6_STR - "Calculate interface cost from bandwidth\n" - "Outgoing metric of this interface\n") +DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd, + "no ipv6 ospf6 cost [(1-65535)]", + NO_STR IP6_STR OSPF6_STR "Calculate interface cost from bandwidth\n" + "Outgoing metric of this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2023,12 +2010,11 @@ DEFUN (no_ipv6_ospf6_cost, return CMD_SUCCESS; } -DEFUN (auto_cost_reference_bandwidth, - auto_cost_reference_bandwidth_cmd, - "auto-cost reference-bandwidth (1-4294967)", - "Calculate OSPF interface cost according to bandwidth\n" - "Use reference bandwidth method to assign OSPF cost\n" - "The reference bandwidth in terms of Mbits per second\n") +DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd, + "auto-cost reference-bandwidth (1-4294967)", + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") { VTY_DECLVAR_CONTEXT(ospf6, o); int idx_number = 2; @@ -2055,13 +2041,11 @@ DEFUN (auto_cost_reference_bandwidth, return CMD_SUCCESS; } -DEFUN (no_auto_cost_reference_bandwidth, - no_auto_cost_reference_bandwidth_cmd, - "no auto-cost reference-bandwidth [(1-4294967)]", - NO_STR - "Calculate OSPF interface cost according to bandwidth\n" - "Use reference bandwidth method to assign OSPF cost\n" - "The reference bandwidth in terms of Mbits per second\n") +DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd, + "no auto-cost reference-bandwidth [(1-4294967)]", + NO_STR "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") { VTY_DECLVAR_CONTEXT(ospf6, o); struct ospf6_area *oa; @@ -2080,11 +2064,10 @@ DEFUN (no_auto_cost_reference_bandwidth, } -DEFUN (ospf6_write_multiplier, - ospf6_write_multiplier_cmd, - "write-multiplier (1-100)", - "Write multiplier\n" - "Maximum number of interface serviced per write\n") +DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd, + "write-multiplier (1-100)", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") { VTY_DECLVAR_CONTEXT(ospf6, o); uint32_t write_oi_count; @@ -2099,12 +2082,10 @@ DEFUN (ospf6_write_multiplier, return CMD_SUCCESS; } -DEFUN (no_ospf6_write_multiplier, - no_ospf6_write_multiplier_cmd, - "no write-multiplier (1-100)", - NO_STR - "Write multiplier\n" - "Maximum number of interface serviced per write\n") +DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd, + "no write-multiplier (1-100)", + NO_STR "Write multiplier\n" + "Maximum number of interface serviced per write\n") { VTY_DECLVAR_CONTEXT(ospf6, o); @@ -2112,13 +2093,9 @@ DEFUN (no_ospf6_write_multiplier, return CMD_SUCCESS; } -DEFUN (ipv6_ospf6_hellointerval, - ipv6_ospf6_hellointerval_cmd, - "ipv6 ospf6 hello-interval (1-65535)", - IP6_STR - OSPF6_STR - "Time between HELLO packets\n" - SECONDS_STR) +DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, + "ipv6 ospf6 hello-interval (1-65535)", + IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2146,23 +2123,15 @@ DEFUN (ipv6_ospf6_hellointerval, return CMD_SUCCESS; } -ALIAS (ipv6_ospf6_hellointerval, - no_ipv6_ospf6_hellointerval_cmd, - "no ipv6 ospf6 hello-interval [(1-65535)]", - NO_STR - IP6_STR - OSPF6_STR - "Time between HELLO packets\n" - SECONDS_STR) +ALIAS(ipv6_ospf6_hellointerval, no_ipv6_ospf6_hellointerval_cmd, + "no ipv6 ospf6 hello-interval [(1-65535)]", + NO_STR IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR) /* interface variable set command */ -DEFUN (ipv6_ospf6_deadinterval, - ipv6_ospf6_deadinterval_cmd, - "ipv6 ospf6 dead-interval (1-65535)", - IP6_STR - OSPF6_STR - "Interval time after which a neighbor is declared down\n" - SECONDS_STR) +DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, + "ipv6 ospf6 dead-interval (1-65535)", + IP6_STR OSPF6_STR + "Interval time after which a neighbor is declared down\n" SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2180,22 +2149,16 @@ DEFUN (ipv6_ospf6_deadinterval, return CMD_SUCCESS; } -ALIAS (ipv6_ospf6_deadinterval, - no_ipv6_ospf6_deadinterval_cmd, - "no ipv6 ospf6 dead-interval [(1-65535)]", - NO_STR - IP6_STR - OSPF6_STR - "Interval time after which a neighbor is declared down\n" - SECONDS_STR) +ALIAS(ipv6_ospf6_deadinterval, no_ipv6_ospf6_deadinterval_cmd, + "no ipv6 ospf6 dead-interval [(1-65535)]", + NO_STR IP6_STR OSPF6_STR + "Interval time after which a neighbor is declared down\n" SECONDS_STR) DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd, "ipv6 ospf6 graceful-restart hello-delay (1-1800)", - IP6_STR - OSPF6_STR - "Graceful Restart parameters\n" - "Delay the sending of the first hello packets.\n" - "Delay in seconds\n") + IP6_STR OSPF6_STR "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2212,12 +2175,9 @@ DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd, DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd, "no ipv6 ospf6 graceful-restart hello-delay [(1-1800)]", - NO_STR - IP6_STR - OSPF6_STR - "Graceful Restart parameters\n" - "Delay the sending of the first hello packets.\n" - "Delay in seconds\n") + NO_STR IP6_STR OSPF6_STR "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2234,13 +2194,9 @@ DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd, } /* interface variable set command */ -DEFUN (ipv6_ospf6_transmitdelay, - ipv6_ospf6_transmitdelay_cmd, - "ipv6 ospf6 transmit-delay (1-3600)", - IP6_STR - OSPF6_STR - "Link state transmit delay\n" - SECONDS_STR) +DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd, + "ipv6 ospf6 transmit-delay (1-3600)", + IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2258,23 +2214,15 @@ DEFUN (ipv6_ospf6_transmitdelay, return CMD_SUCCESS; } -ALIAS (ipv6_ospf6_transmitdelay, - no_ipv6_ospf6_transmitdelay_cmd, - "no ipv6 ospf6 transmit-delay [(1-3600)]", - NO_STR - IP6_STR - OSPF6_STR - "Link state transmit delay\n" - SECONDS_STR) +ALIAS(ipv6_ospf6_transmitdelay, no_ipv6_ospf6_transmitdelay_cmd, + "no ipv6 ospf6 transmit-delay [(1-3600)]", + NO_STR IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR) /* interface variable set command */ -DEFUN (ipv6_ospf6_retransmitinterval, - ipv6_ospf6_retransmitinterval_cmd, - "ipv6 ospf6 retransmit-interval (1-65535)", - IP6_STR - OSPF6_STR - "Time between retransmitting lost link state advertisements\n" - SECONDS_STR) +DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd, + "ipv6 ospf6 retransmit-interval (1-65535)", + IP6_STR OSPF6_STR + "Time between retransmitting lost link state advertisements\n" SECONDS_STR) { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2292,23 +2240,16 @@ DEFUN (ipv6_ospf6_retransmitinterval, return CMD_SUCCESS; } -ALIAS (ipv6_ospf6_retransmitinterval, - no_ipv6_ospf6_retransmitinterval_cmd, - "no ipv6 ospf6 retransmit-interval [(1-65535)]", - NO_STR - IP6_STR - OSPF6_STR - "Time between retransmitting lost link state advertisements\n" - SECONDS_STR) +ALIAS(ipv6_ospf6_retransmitinterval, no_ipv6_ospf6_retransmitinterval_cmd, + "no ipv6 ospf6 retransmit-interval [(1-65535)]", + NO_STR IP6_STR OSPF6_STR + "Time between retransmitting lost link state advertisements\n" SECONDS_STR) /* interface variable set command */ -DEFUN (ipv6_ospf6_priority, - ipv6_ospf6_priority_cmd, - "ipv6 ospf6 priority (0-255)", - IP6_STR - OSPF6_STR - "Router priority\n" - "Priority value\n") +DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd, + "ipv6 ospf6 priority (0-255)", + IP6_STR OSPF6_STR "Router priority\n" + "Priority value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2324,10 +2265,9 @@ DEFUN (ipv6_ospf6_priority, ? OSPF6_INTERFACE_PRIORITY : strtoul(argv[idx_number]->arg, NULL, 10); - if (oi->area - && (oi->state == OSPF6_INTERFACE_DROTHER - || oi->state == OSPF6_INTERFACE_BDR - || oi->state == OSPF6_INTERFACE_DR)) { + if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER || + oi->state == OSPF6_INTERFACE_BDR || + oi->state == OSPF6_INTERFACE_DR)) { if (ospf6_interface_state_change(dr_election(oi), oi) == -1) OSPF6_LINK_LSA_SCHEDULE(oi); } @@ -2335,22 +2275,15 @@ DEFUN (ipv6_ospf6_priority, return CMD_SUCCESS; } -ALIAS (ipv6_ospf6_priority, - no_ipv6_ospf6_priority_cmd, - "no ipv6 ospf6 priority [(0-255)]", - NO_STR - IP6_STR - OSPF6_STR - "Router priority\n" - "Priority value\n") +ALIAS(ipv6_ospf6_priority, no_ipv6_ospf6_priority_cmd, + "no ipv6 ospf6 priority [(0-255)]", + NO_STR IP6_STR OSPF6_STR "Router priority\n" + "Priority value\n") -DEFUN (ipv6_ospf6_instance, - ipv6_ospf6_instance_cmd, - "ipv6 ospf6 instance-id (0-255)", - IP6_STR - OSPF6_STR - "Instance ID for this interface\n" - "Instance ID value\n") +DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd, + "ipv6 ospf6 instance-id (0-255)", + IP6_STR OSPF6_STR "Instance ID for this interface\n" + "Instance ID value\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_number = 3; @@ -2368,22 +2301,14 @@ DEFUN (ipv6_ospf6_instance, return CMD_SUCCESS; } -ALIAS (ipv6_ospf6_instance, - no_ipv6_ospf6_instance_cmd, - "no ipv6 ospf6 instance-id [(0-255)]", - NO_STR - IP6_STR - OSPF6_STR - "Instance ID for this interface\n" - "Instance ID value\n") +ALIAS(ipv6_ospf6_instance, no_ipv6_ospf6_instance_cmd, + "no ipv6 ospf6 instance-id [(0-255)]", + NO_STR IP6_STR OSPF6_STR "Instance ID for this interface\n" + "Instance ID value\n") -DEFUN (ipv6_ospf6_passive, - ipv6_ospf6_passive_cmd, - "ipv6 ospf6 passive", - IP6_STR - OSPF6_STR - "Passive interface; no adjacency will be formed on this interface\n" - ) +DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive", + IP6_STR OSPF6_STR + "Passive interface; no adjacency will be formed on this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2409,14 +2334,9 @@ DEFUN (ipv6_ospf6_passive, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_passive, - no_ipv6_ospf6_passive_cmd, - "no ipv6 ospf6 passive", - NO_STR - IP6_STR - OSPF6_STR - "passive interface: No Adjacency will be formed on this I/F\n" - ) +DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive", + NO_STR IP6_STR OSPF6_STR + "passive interface: No Adjacency will be formed on this I/F\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2439,13 +2359,8 @@ DEFUN (no_ipv6_ospf6_passive, return CMD_SUCCESS; } -DEFUN (ipv6_ospf6_mtu_ignore, - ipv6_ospf6_mtu_ignore_cmd, - "ipv6 ospf6 mtu-ignore", - IP6_STR - OSPF6_STR - "Disable MTU mismatch detection on this interface\n" - ) +DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore", + IP6_STR OSPF6_STR "Disable MTU mismatch detection on this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2461,14 +2376,10 @@ DEFUN (ipv6_ospf6_mtu_ignore, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_mtu_ignore, - no_ipv6_ospf6_mtu_ignore_cmd, - "no ipv6 ospf6 mtu-ignore", - NO_STR - IP6_STR - OSPF6_STR - "Disable MTU mismatch detection on this interface\n" - ) +DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd, + "no ipv6 ospf6 mtu-ignore", + NO_STR IP6_STR OSPF6_STR + "Disable MTU mismatch detection on this interface\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2484,15 +2395,11 @@ DEFUN (no_ipv6_ospf6_mtu_ignore, return CMD_SUCCESS; } -DEFUN (ipv6_ospf6_advertise_prefix_list, - ipv6_ospf6_advertise_prefix_list_cmd, - "ipv6 ospf6 advertise prefix-list WORD", - IP6_STR - OSPF6_STR - "Advertising options\n" - "Filter prefix using prefix-list\n" - "Prefix list name\n" - ) +DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd, + "ipv6 ospf6 advertise prefix-list PREFIXLIST6_NAME", + IP6_STR OSPF6_STR "Advertising options\n" + "Filter prefix using prefix-list\n" + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_word = 4; @@ -2522,15 +2429,12 @@ DEFUN (ipv6_ospf6_advertise_prefix_list, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_advertise_prefix_list, - no_ipv6_ospf6_advertise_prefix_list_cmd, - "no ipv6 ospf6 advertise prefix-list [WORD]", - NO_STR - IP6_STR - OSPF6_STR - "Advertising options\n" - "Filter prefix using prefix-list\n" - "Prefix list name\n") +DEFUN(no_ipv6_ospf6_advertise_prefix_list, + no_ipv6_ospf6_advertise_prefix_list_cmd, + "no ipv6 ospf6 advertise prefix-list [PREFIXLIST6_NAME]", + NO_STR IP6_STR OSPF6_STR "Advertising options\n" + "Filter prefix using prefix-list\n" + "Prefix list name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2558,15 +2462,12 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list, return CMD_SUCCESS; } -DEFUN (ipv6_ospf6_network, - ipv6_ospf6_network_cmd, - "ipv6 ospf6 network ", - IP6_STR - OSPF6_STR - "Network type\n" - "Specify OSPF6 broadcast network\n" - "Specify OSPF6 point-to-point network\n" - ) +DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd, + "ipv6 ospf6 network ", + IP6_STR OSPF6_STR "Network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 point-to-multipoint network\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int idx_network = 3; @@ -2591,6 +2492,11 @@ DEFUN (ipv6_ospf6_network, return CMD_SUCCESS; } oi->type = OSPF_IFTYPE_POINTOPOINT; + } else if (strncmp(argv[idx_network]->arg, "point-to-m", 10) == 0) { + if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) { + return CMD_SUCCESS; + } + oi->type = OSPF_IFTYPE_POINTOMULTIPOINT; } /* Reset the interface */ @@ -2600,15 +2506,11 @@ DEFUN (ipv6_ospf6_network, return CMD_SUCCESS; } -DEFUN (no_ipv6_ospf6_network, - no_ipv6_ospf6_network_cmd, - "no ipv6 ospf6 network []", - NO_STR - IP6_STR - OSPF6_STR - "Set default network type\n" - "Specify OSPF6 broadcast network\n" - "Specify OSPF6 point-to-point network\n") +DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd, + "no ipv6 ospf6 network []", + NO_STR IP6_STR OSPF6_STR "Set default network type\n" + "Specify OSPF6 broadcast network\n" + "Specify OSPF6 point-to-point network\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -2617,9 +2519,8 @@ DEFUN (no_ipv6_ospf6_network, assert(ifp); oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) { + if (oi == NULL) return CMD_SUCCESS; - } oi->type_cfg = false; @@ -2636,6 +2537,95 @@ DEFUN (no_ipv6_ospf6_network, return CMD_SUCCESS; } +DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd, + "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only", + NO_STR IP6_STR OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Only form adjacencies with explicitly configured neighbors\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi = ifp->info; + + if (no) { + if (!oi) + return CMD_SUCCESS; + + oi->p2xp_only_cfg_neigh = false; + return CMD_SUCCESS; + } + + if (!oi) + oi = ospf6_interface_create(ifp); + + oi->p2xp_only_cfg_neigh = true; + return CMD_SUCCESS; +} + +DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd, + "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello", + NO_STR IP6_STR OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Do not send multicast hellos\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi = ifp->info; + + if (no) { + if (!oi) + return CMD_SUCCESS; + + oi->p2xp_no_multicast_hello = false; + return CMD_SUCCESS; + } + + if (!oi) + oi = ospf6_interface_create(ifp); + + oi->p2xp_no_multicast_hello = true; + return CMD_SUCCESS; +} + +DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd, + "[no] ipv6 ospf6 p2p-p2mp connected-prefixes ", + NO_STR IP6_STR OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Adjust handling of directly connected prefixes\n" + "Advertise prefixes and own /128 (default for PtP)\n" + "Ignore, only advertise own /128 (default for PtMP)\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi = ifp->info; + bool old_incl, old_excl; + + if (no && !oi) + return CMD_SUCCESS; + + if (!oi) + oi = ospf6_interface_create(ifp); + + old_incl = oi->p2xp_connected_pfx_include; + old_excl = oi->p2xp_connected_pfx_exclude; + oi->p2xp_connected_pfx_include = false; + oi->p2xp_connected_pfx_exclude = false; + + if (incl && !no) + oi->p2xp_connected_pfx_include = true; + if (excl && !no) + oi->p2xp_connected_pfx_exclude = true; + + if (oi->p2xp_connected_pfx_include != old_incl || + oi->p2xp_connected_pfx_exclude != old_excl) + ospf6_interface_connected_route_update(ifp); + return CMD_SUCCESS; +} + +ALIAS(ipv6_ospf6_p2xp_connected_pfx, no_ipv6_ospf6_p2xp_connected_pfx_cmd, + "no ipv6 ospf6 p2p-p2mp connected-prefixes", + NO_STR IP6_STR OSPF6_STR + "Point-to-point and Point-to-Multipoint parameters\n" + "Adjust handling of directly connected prefixes\n") + + static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) { struct ospf6_interface *oi; @@ -2695,7 +2685,10 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) if (oi->mtu_ignore) vty_out(vty, " ipv6 ospf6 mtu-ignore\n"); - if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT) + if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + vty_out(vty, + " ipv6 ospf6 network point-to-multipoint\n"); + else if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT) vty_out(vty, " ipv6 ospf6 network point-to-point\n"); else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST) vty_out(vty, " ipv6 ospf6 network broadcast\n"); @@ -2704,7 +2697,22 @@ static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf) vty_out(vty, " ipv6 ospf6 graceful-restart hello-delay %u\n", oi->gr.hello_delay.interval); + if (oi->p2xp_only_cfg_neigh) + vty_out(vty, + " ipv6 ospf6 p2p-p2mp config-neighbors-only\n"); + if (oi->p2xp_no_multicast_hello) + vty_out(vty, + " ipv6 ospf6 p2p-p2mp disable-multicast-hello\n"); + + if (oi->p2xp_connected_pfx_include) + vty_out(vty, + " ipv6 ospf6 p2p-p2mp connected-prefixes include\n"); + else if (oi->p2xp_connected_pfx_exclude) + vty_out(vty, + " ipv6 ospf6 p2p-p2mp connected-prefixes exclude\n"); + + config_write_ospf6_p2xp_neighbor(vty, oi); ospf6_bfd_write_config(vty, oi); ospf6_auth_write_config(vty, &oi->at_data); @@ -2742,10 +2750,10 @@ static int ospf6_ifp_create(struct interface *ifp) static int ospf6_ifp_up(struct interface *ifp) { if (IS_OSPF6_DEBUG_ZEBRA(RECV)) - zlog_debug( - "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6, ifp->bandwidth); + zlog_debug("Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", + ifp->name, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, + ifp->mtu6, ifp->bandwidth); ospf6_interface_state_update(ifp); @@ -2755,10 +2763,10 @@ static int ospf6_ifp_up(struct interface *ifp) static int ospf6_ifp_down(struct interface *ifp) { if (IS_OSPF6_DEBUG_ZEBRA(RECV)) - zlog_debug( - "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", - ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, - ifp->metric, ifp->mtu6, ifp->bandwidth); + zlog_debug("Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d", + ifp->name, ifp->ifindex, + (unsigned long long)ifp->flags, ifp->metric, + ifp->mtu6, ifp->bandwidth); ospf6_interface_state_update(ifp); @@ -2785,13 +2793,14 @@ void ospf6_interface_init(void) { /* Install interface node. */ if_cmd_init(config_write_interface); - if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up, - ospf6_ifp_down, ospf6_ifp_destroy); + hook_register_prio(if_real, 0, ospf6_ifp_create); + hook_register_prio(if_up, 0, ospf6_ifp_up); + hook_register_prio(if_down, 0, ospf6_ifp_down); + hook_register_prio(if_unreal, 0, ospf6_ifp_destroy); install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd); install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd); - install_element(VIEW_NODE, - &show_ipv6_ospf6_interface_ifname_prefix_cmd); + install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd); install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd); install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd); @@ -2829,6 +2838,11 @@ void ospf6_interface_init(void) install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd); install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_only_cfg_neigh_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_no_multicast_hello_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_connected_pfx_cmd); + install_element(INTERFACE_NODE, &no_ipv6_ospf6_p2xp_connected_pfx_cmd); + /* reference bandwidth commands */ install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd); install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd); @@ -2859,16 +2873,9 @@ void ospf6_interface_clear(struct interface *ifp) } /* Clear interface */ -DEFUN (clear_ipv6_ospf6_interface, - clear_ipv6_ospf6_interface_cmd, - "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", - CLEAR_STR - IP6_STR - OSPF6_STR - VRF_CMD_HELP_STR - INTERFACE_STR - IFNAME_STR - ) +DEFUN(clear_ipv6_ospf6_interface, clear_ipv6_ospf6_interface_cmd, + "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]", + CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR INTERFACE_STR IFNAME_STR) { struct vrf *vrf; int idx_vrf = 3; @@ -2909,26 +2916,16 @@ void install_element_ospf6_clear_interface(void) install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd); } -DEFUN (debug_ospf6_interface, - debug_ospf6_interface_cmd, - "debug ospf6 interface", - DEBUG_STR - OSPF6_STR - "Debug OSPFv3 Interface\n" - ) +DEFUN(debug_ospf6_interface, debug_ospf6_interface_cmd, "debug ospf6 interface", + DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n") { OSPF6_DEBUG_INTERFACE_ON(); return CMD_SUCCESS; } -DEFUN (no_debug_ospf6_interface, - no_debug_ospf6_interface_cmd, - "no debug ospf6 interface", - NO_STR - DEBUG_STR - OSPF6_STR - "Debug OSPFv3 Interface\n" - ) +DEFUN(no_debug_ospf6_interface, no_debug_ospf6_interface_cmd, + "no debug ospf6 interface", + NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n") { OSPF6_DEBUG_INTERFACE_OFF(); return CMD_SUCCESS; @@ -2965,10 +2962,9 @@ void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data) DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, ipv6_ospf6_intf_auth_trailer_keychain_cmd, "ipv6 ospf6 authentication keychain KEYCHAIN_NAME", - IP6_STR OSPF6_STR - "Enable authentication on this interface\n" - "Keychain\n" - "Keychain name\n") + IP6_STR OSPF6_STR "Enable authentication on this interface\n" + "Keychain\n" + "Keychain name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int keychain_idx = 4; @@ -2989,8 +2985,8 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, if (oi->at_data.keychain) XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain); - oi->at_data.keychain = - XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg); + oi->at_data.keychain = XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, + argv[keychain_idx]->arg); return CMD_SUCCESS; } @@ -2998,10 +2994,9 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_keychain, DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain, no_ipv6_ospf6_intf_auth_trailer_keychain_cmd, "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]", - NO_STR IP6_STR OSPF6_STR - "Enable authentication on this interface\n" - "Keychain\n" - "Keychain name\n") + NO_STR IP6_STR OSPF6_STR "Enable authentication on this interface\n" + "Keychain\n" + "Keychain name\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; @@ -3027,18 +3022,17 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd, "ipv6 ospf6 authentication key-id (1-65535) hash-algo " " " "key WORD", - IP6_STR OSPF6_STR - "Authentication\n" - "Key ID\n" - "Key ID value\n" - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n" - "Password\n" - "Password string (key)\n") + IP6_STR OSPF6_STR "Authentication\n" + "Key ID\n" + "Key ID value\n" + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n" + "Password\n" + "Password string (key)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); int key_id_idx = 4; @@ -3072,8 +3066,8 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd, oi->at_data.key_id = (uint16_t)strtol(argv[key_id_idx]->arg, NULL, 10); if (oi->at_data.auth_key) XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key); - oi->at_data.auth_key = - XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, argv[password_idx]->arg); + oi->at_data.auth_key = XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, + argv[password_idx]->arg); return CMD_SUCCESS; } @@ -3083,18 +3077,17 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_key, "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo " " " "key WORD]", - NO_STR IP6_STR OSPF6_STR - "Authentication\n" - "Key ID\n" - "Key ID value\n" - "Cryptographic-algorithm\n" - "Use MD5 algorithm\n" - "Use HMAC-SHA-1 algorithm\n" - "Use HMAC-SHA-256 algorithm\n" - "Use HMAC-SHA-384 algorithm\n" - "Use HMAC-SHA-512 algorithm\n" - "Password\n" - "Password string (key)\n") + NO_STR IP6_STR OSPF6_STR "Authentication\n" + "Key ID\n" + "Key ID value\n" + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n" + "Password\n" + "Password string (key)\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct ospf6_interface *oi; diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 5942df0..46a7c90 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -34,6 +34,25 @@ struct ospf6_auth_data { uint32_t rx_drop; /* Pkt drop due to auth fail while reading */ }; +PREDECL_RBTREE_UNIQ(ospf6_if_p2xp_neighcfgs); + +struct ospf6_if_p2xp_neighcfg { + struct ospf6_if_p2xp_neighcfgs_item item; + + struct ospf6_interface *ospf6_if; + struct in6_addr addr; + + bool cfg_cost : 1; + + uint32_t cost; + uint16_t poll_interval; + + /* NULL if down */ + struct ospf6_neighbor *active; + + struct event *t_unicast_hello; +}; + /* Interface structure */ struct ospf6_interface { /* IF info from zebra */ @@ -66,6 +85,20 @@ struct ospf6_interface { uint8_t type; bool type_cfg; + /* P2P/P2MP behavior: */ + + /* disable hellos on standard multicast? */ + bool p2xp_no_multicast_hello; + /* only allow explicitly configured neighbors? */ + bool p2xp_only_cfg_neigh; + /* override mode default for advertising connected prefixes. + * both false by default (= do include for PtP, exclude for PtMP) + */ + bool p2xp_connected_pfx_include; + bool p2xp_connected_pfx_exclude; + + struct ospf6_if_p2xp_neighcfgs_head p2xp_neighs; + /* Router Priority */ uint8_t priority; @@ -171,15 +204,16 @@ struct ospf6_interface { DECLARE_QOBJ_TYPE(ospf6_interface); /* interface state */ -#define OSPF6_INTERFACE_NONE 0 -#define OSPF6_INTERFACE_DOWN 1 -#define OSPF6_INTERFACE_LOOPBACK 2 -#define OSPF6_INTERFACE_WAITING 3 -#define OSPF6_INTERFACE_POINTTOPOINT 4 -#define OSPF6_INTERFACE_DROTHER 5 -#define OSPF6_INTERFACE_BDR 6 -#define OSPF6_INTERFACE_DR 7 -#define OSPF6_INTERFACE_MAX 8 +#define OSPF6_INTERFACE_NONE 0 +#define OSPF6_INTERFACE_DOWN 1 +#define OSPF6_INTERFACE_LOOPBACK 2 +#define OSPF6_INTERFACE_WAITING 3 +#define OSPF6_INTERFACE_POINTTOPOINT 4 +#define OSPF6_INTERFACE_POINTTOMULTIPOINT 5 +#define OSPF6_INTERFACE_DROTHER 6 +#define OSPF6_INTERFACE_BDR 7 +#define OSPF6_INTERFACE_DR 8 +#define OSPF6_INTERFACE_MAX 9 extern const char *const ospf6_interface_state_str[]; @@ -197,7 +231,7 @@ extern const char *const ospf6_interface_state_str[]; #define OSPF6_INTERFACE_TRANSDELAY 1 #define OSPF6_INTERFACE_INSTANCE_ID 0 #define OSPF6_INTERFACE_BANDWIDTH 10000 /* Mbps */ -#define OSPF6_REFERENCE_BANDWIDTH 100000 /* Mbps */ +#define OSPF6_REFERENCE_BANDWIDTH 100000 /* Kbps */ #define OSPF6_INTERFACE_SSO_RETRY_INT 1 #define OSPF6_INTERFACE_SSO_RETRY_MAX 5 diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index eb5514a..cb03675 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -321,13 +321,14 @@ void ospf6_router_lsa_originate(struct event *thread) } /* Point-to-Point interfaces */ - if (oi->type == OSPF_IFTYPE_POINTOPOINT) { + if (oi->type == OSPF_IFTYPE_POINTOPOINT + || oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) { for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) { if (on->state != OSPF6_NEIGHBOR_FULL) continue; lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT; - lsdesc->metric = htons(oi->cost); + lsdesc->metric = htons(ospf6_neighbor_cost(on)); lsdesc->interface_id = htonl(oi->interface->ifindex); lsdesc->neighbor_interface_id = @@ -1068,6 +1069,7 @@ void ospf6_intra_prefix_lsa_originate_stub(struct event *thread) if (oi->state != OSPF6_INTERFACE_LOOPBACK && oi->state != OSPF6_INTERFACE_POINTTOPOINT + && oi->state != OSPF6_INTERFACE_POINTTOMULTIPOINT && full_count != 0) { if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX)) zlog_debug(" Interface %s is not stub, ignore", diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 9323045..17966e7 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -38,8 +38,13 @@ /* Default configuration file name for ospf6d. */ #define OSPF6_DEFAULT_CONFIG "ospf6d.conf" -/* Default port values. */ -#define OSPF6_VTY_PORT 2606 +/* GR and auth trailer persistent state */ +#define OSPF6D_STATE_NAME "%s/ospf6d.json", frr_libstatedir +#define OSPF6D_COMPAT_STATE_NAME "%s/ospf6d-gr.json", frr_runstatedir +/* for extra confusion, "ospf6d-at-seq-no.dat" is handled directly in + * ospf6_auth_trailer.c; the alternative would be somehow merging JSON which + * is excessive for just supporting a legacy compatibility file location + */ /* ospf6d privileges */ zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN}; @@ -103,7 +108,11 @@ static void __attribute__((noreturn)) ospf6_exit(int status) zclient_free(zclient); } + ospf6_master_delete(); + frr_fini(); + + keychain_terminate(); exit(status); } @@ -162,16 +171,31 @@ static const struct frr_yang_module_info *const ospf6d_yang_modules[] = { &frr_ospf6_route_map_info, }; -FRR_DAEMON_INFO(ospf6d, OSPF6, .vty_port = OSPF6_VTY_PORT, +/* actual paths filled in main() */ +static char state_path[512]; +static char state_compat_path[512]; +static char *state_paths[] = { + state_path, + state_compat_path, + NULL, +}; - .proghelp = "Implementation of the OSPFv3 routing protocol.", +/* clang-format off */ +FRR_DAEMON_INFO(ospf6d, OSPF6, + .vty_port = OSPF6_VTY_PORT, + .proghelp = "Implementation of the OSPFv3 routing protocol.", - .signals = ospf6_signals, - .n_signals = array_size(ospf6_signals), + .signals = ospf6_signals, + .n_signals = array_size(ospf6_signals), - .privs = &ospf6d_privs, .yang_modules = ospf6d_yang_modules, - .n_yang_modules = array_size(ospf6d_yang_modules), + .privs = &ospf6d_privs, + + .yang_modules = ospf6d_yang_modules, + .n_yang_modules = array_size(ospf6d_yang_modules), + + .state_paths = state_paths, ); +/* clang-format on */ /* Max wait time for config to load before accepting hellos */ #define OSPF6_PRE_CONFIG_MAX_WAIT_SECONDS 600 @@ -229,6 +253,10 @@ int main(int argc, char *argv[], char *envp[]) exit(1); } + snprintf(state_path, sizeof(state_path), OSPF6D_STATE_NAME); + snprintf(state_compat_path, sizeof(state_compat_path), + OSPF6D_COMPAT_STATE_NAME); + /* OSPF6 master init. */ ospf6_master_init(frr_init()); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 07da9a5..d13799c 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -268,6 +268,18 @@ static struct ospf6_packet *ospf6_packet_new(size_t size) return new; } +static struct ospf6_packet *ospf6_packet_dup(struct ospf6_packet *old) +{ + struct ospf6_packet *new; + + new = XCALLOC(MTYPE_OSPF6_PACKET, sizeof(struct ospf6_packet)); + new->s = stream_dup(old->s); + new->dst = old->dst; + new->length = old->length; + + return new; +} + static void ospf6_packet_free(struct ospf6_packet *op) { if (op->s) @@ -407,6 +419,25 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, hello = (struct ospf6_hello *)((caddr_t)oh + sizeof(struct ospf6_header)); + if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT + || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT) + && oi->p2xp_only_cfg_neigh) { + /* NEVER, never, ever, do this on broadcast (or NBMA)! + * DR/BDR election requires everyone to talk to everyone else + * only for PtP/PtMP we can be selective in adjacencies! + */ + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + + p2xp_cfg = ospf6_if_p2xp_find(oi, src); + if (!p2xp_cfg) { + if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) + zlog_debug( + "ignoring PtP/PtMP hello from %pI6, neighbor not configured", + src); + return; + } + } + /* HelloInterval check */ if (ntohs(hello->hello_interval) != oi->hello_interval) { zlog_warn( @@ -479,7 +510,7 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst, on->hello_in++; /* Always override neighbor's source address */ - memcpy(&on->linklocal_addr, src, sizeof(struct in6_addr)); + ospf6_neighbor_lladdr_set(on, src); /* Neighbor ifindex check */ if (on->ifindex != (ifindex_t)ntohl(hello->interface_id)) { @@ -631,8 +662,8 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, "Neighbor state is not ExStart, ignore"); return; } - /* else fall through to ExStart */ - /* fallthru */ + /* else fall through to ExStart */ + fallthrough; case OSPF6_NEIGHBOR_EXSTART: /* if neighbor obeys us as our slave, schedule negotiation_done and process LSA Headers. Otherwise, ignore this message */ @@ -650,8 +681,8 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh, on->ospf6_if->interface->vrf->name, on->name); return; } - /* fall through to exchange */ - + /* fall through to exchange */ + fallthrough; case OSPF6_NEIGHBOR_EXCHANGE: if (!memcmp(dbdesc, &on->dbdesc_last, sizeof(struct ospf6_dbdesc))) { @@ -835,8 +866,8 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh, "Neighbor state is not ExStart, ignore"); return; } - /* else fall through to ExStart */ - /* fallthru */ + /* else fall through to ExStart */ + fallthrough; case OSPF6_NEIGHBOR_EXSTART: /* If the neighbor is Master, act as Slave. Schedule negotiation_done @@ -2239,8 +2270,6 @@ static void ospf6_write(struct event *thread) void ospf6_hello_send(struct event *thread) { struct ospf6_interface *oi; - struct ospf6_packet *op; - uint16_t length = OSPF6_HEADER_SIZE; oi = (struct ospf6_interface *)EVENT_ARG(thread); @@ -2266,6 +2295,20 @@ void ospf6_hello_send(struct event *thread) return; } + event_add_timer(master, ospf6_hello_send, oi, oi->hello_interval, + &oi->thread_send_hello); + + ospf6_hello_send_addr(oi, NULL); +} + +/* used to send polls for PtP/PtMP too */ +void ospf6_hello_send_addr(struct ospf6_interface *oi, + const struct in6_addr *addr) +{ + struct ospf6_packet *op; + uint16_t length = OSPF6_HEADER_SIZE; + bool anything = false; + op = ospf6_packet_new(oi->ifmtu); ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO, oi, op->s); @@ -2284,20 +2327,40 @@ void ospf6_hello_send(struct event *thread) /* Set packet length. */ op->length = length; - op->dst = allspfrouters6; - - ospf6_fill_hdr_checksum(oi, op); + if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT + || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT) + && !addr && oi->p2xp_no_multicast_hello) { + struct listnode *node; + struct ospf6_neighbor *on; + struct ospf6_packet *opdup; + + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) { + if (on->state < OSPF6_NEIGHBOR_INIT) + /* poll-interval for these */ + continue; + + opdup = ospf6_packet_dup(op); + opdup->dst = on->linklocal_addr; + ospf6_fill_hdr_checksum(oi, opdup); + ospf6_packet_add_top(oi, opdup); + anything = true; + } - /* Add packet to the top of the interface output queue, so that they - * can't get delayed by things like long queues of LS Update packets - */ - ospf6_packet_add_top(oi, op); + ospf6_packet_free(op); + } else { + op->dst = addr ? *addr : allspfrouters6; - /* set next thread */ - event_add_timer(master, ospf6_hello_send, oi, oi->hello_interval, - &oi->thread_send_hello); + /* Add packet to the top of the interface output queue, so that + * they can't get delayed by things like long queues of LS + * Update packets + */ + ospf6_fill_hdr_checksum(oi, op); + ospf6_packet_add_top(oi, op); + anything = true; + } - OSPF6_MESSAGE_WRITE_ON(oi); + if (anything) + OSPF6_MESSAGE_WRITE_ON(oi); } static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s) diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h index 2b25b07..2434079 100644 --- a/ospf6d/ospf6_message.h +++ b/ospf6d/ospf6_message.h @@ -50,6 +50,8 @@ extern unsigned char conf_debug_ospf6_message[]; #define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */ #define OSPF6_MESSAGE_TYPE_MAX 0x6 /* same as OSPF6_MESSAGE_TYPE_ALL */ +struct ospf6_interface; + struct ospf6_packet { struct ospf6_packet *next; @@ -169,6 +171,9 @@ extern void ospf6_lsupdate_send_neighbor(struct event *thread); extern void ospf6_lsack_send_interface(struct event *thread); extern void ospf6_lsack_send_neighbor(struct event *thread); +extern void ospf6_hello_send_addr(struct ospf6_interface *oi, + const struct in6_addr *addr); + extern int config_write_ospf6_debug_message(struct vty *); extern void install_element_ospf6_debug_message(void); extern const char *ospf6_message_type(int type); diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index e1aec06..a6089b2 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -34,6 +34,16 @@ #include "lib/json.h" DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR, "OSPF6 neighbor"); +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_NEIGHBOR_P2XP_CFG, + "OSPF6 PtP/PtMP neighbor config"); + +static int ospf6_if_p2xp_neighcfg_cmp(const struct ospf6_if_p2xp_neighcfg *a, + const struct ospf6_if_p2xp_neighcfg *b); + +DECLARE_RBTREE_UNIQ(ospf6_if_p2xp_neighcfgs, struct ospf6_if_p2xp_neighcfg, + item, ospf6_if_p2xp_neighcfg_cmp); + +static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost); DEFINE_HOOK(ospf6_neighbor_change, (struct ospf6_neighbor * on, int state, int next_state), @@ -42,13 +52,14 @@ DEFINE_HOOK(ospf6_neighbor_change, unsigned char conf_debug_ospf6_neighbor = 0; const char *const ospf6_neighbor_state_str[] = { - "None", "Down", "Attempt", "Init", "Twoway", - "ExStart", "ExChange", "Loading", "Full", NULL}; + "None", "Down", "Attempt", "Init", "Twoway", + "ExStart", "ExChange", "Loading", "Full", NULL +}; const char *const ospf6_neighbor_event_str[] = { - "NoEvent", "HelloReceived", "2-WayReceived", "NegotiationDone", - "ExchangeDone", "LoadingDone", "AdjOK?", "SeqNumberMismatch", - "BadLSReq", "1-WayReceived", "InactivityTimer", + "NoEvent", "HelloReceived", "2-WayReceived", "NegotiationDone", + "ExchangeDone", "LoadingDone", "AdjOK?", "SeqNumberMismatch", + "BadLSReq", "1-WayReceived", "InactivityTimer", }; int ospf6_neighbor_cmp(void *va, void *vb) @@ -119,8 +130,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor)); inet_ntop(AF_INET, &router_id, buf, sizeof(buf)); - snprintf(on->name, sizeof(on->name), "%s%%%s", buf, - oi->interface->name); + snprintf(on->name, sizeof(on->name), "%s%%%s", buf, oi->interface->name); on->ospf6_if = oi; on->state = OSPF6_NEIGHBOR_DOWN; on->state_change = 0; @@ -150,6 +160,9 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, void ospf6_neighbor_delete(struct ospf6_neighbor *on) { + if (on->p2xp_cfg) + on->p2xp_cfg->active = NULL; + ospf6_neighbor_clear_ls_lists(on); ospf6_lsdb_remove_all(on->dbdesc_list); @@ -182,6 +195,22 @@ void ospf6_neighbor_delete(struct ospf6_neighbor *on) XFREE(MTYPE_OSPF6_NEIGHBOR, on); } +void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on, + const struct in6_addr *addr) +{ + if (IPV6_ADDR_SAME(addr, &on->linklocal_addr)) + return; + + memcpy(&on->linklocal_addr, addr, sizeof(struct in6_addr)); + + if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT || + on->ospf6_if->type == OSPF_IFTYPE_POINTOMULTIPOINT) { + uint32_t prev_cost = ospf6_neighbor_cost(on); + + p2xp_neigh_refresh(on, prev_cost); + } +} + static void ospf6_neighbor_state_change(uint8_t next_state, struct ospf6_neighbor *on, int event) { @@ -198,31 +227,28 @@ static void ospf6_neighbor_state_change(uint8_t next_state, /* log */ if (IS_OSPF6_DEBUG_NEIGHBOR(STATE)) { - zlog_debug( - "Neighbor state change %s (Router-ID: %pI4): [%s]->[%s] (%s)", - on->name, &on->router_id, - ospf6_neighbor_state_str[prev_state], - ospf6_neighbor_state_str[next_state], - ospf6_neighbor_event_string(event)); + zlog_debug("Neighbor state change %s (Router-ID: %pI4): [%s]->[%s] (%s)", + on->name, &on->router_id, + ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state], + ospf6_neighbor_event_string(event)); } /* Optionally notify about adjacency changes */ if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, - OSPF6_LOG_ADJACENCY_CHANGES) - && (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, - OSPF6_LOG_ADJACENCY_DETAIL) - || (next_state == OSPF6_NEIGHBOR_FULL) - || (next_state < prev_state))) - zlog_notice( - "AdjChg: Nbr %pI4(%s) on %s: %s -> %s (%s)", - &on->router_id, - vrf_id_to_name(on->ospf6_if->interface->vrf->vrf_id), - on->name, ospf6_neighbor_state_str[prev_state], - ospf6_neighbor_state_str[next_state], - ospf6_neighbor_event_string(event)); - - if (prev_state == OSPF6_NEIGHBOR_FULL - || next_state == OSPF6_NEIGHBOR_FULL) { + OSPF6_LOG_ADJACENCY_CHANGES) && + (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags, + OSPF6_LOG_ADJACENCY_DETAIL) || + (next_state == OSPF6_NEIGHBOR_FULL) || (next_state < prev_state))) + zlog_notice("AdjChg: Nbr %pI4(%s) on %s: %s -> %s (%s)", + &on->router_id, + vrf_id_to_name(on->ospf6_if->interface->vrf->vrf_id), + on->name, ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state], + ospf6_neighbor_event_string(event)); + + if (prev_state == OSPF6_NEIGHBOR_FULL || + next_state == OSPF6_NEIGHBOR_FULL) { if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) { OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area); if (on->ospf6_if->state == OSPF6_INTERFACE_DR) { @@ -235,12 +261,11 @@ static void ospf6_neighbor_state_change(uint8_t next_state, on->ospf6_if->area->intra_prefix_originate = 1; if (!OSPF6_GR_IS_ACTIVE_HELPER(on)) - OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB( - on->ospf6_if->area); + OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(on->ospf6_if->area); - if ((prev_state == OSPF6_NEIGHBOR_LOADING - || prev_state == OSPF6_NEIGHBOR_EXCHANGE) - && next_state == OSPF6_NEIGHBOR_FULL) { + if ((prev_state == OSPF6_NEIGHBOR_LOADING || + prev_state == OSPF6_NEIGHBOR_EXCHANGE) && + next_state == OSPF6_NEIGHBOR_FULL) { OSPF6_AS_EXTERN_LSA_SCHEDULE(on->ospf6_if); on->ospf6_if->area->full_nbrs++; } @@ -249,10 +274,10 @@ static void ospf6_neighbor_state_change(uint8_t next_state, on->ospf6_if->area->full_nbrs--; } - if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE - || prev_state == OSPF6_NEIGHBOR_LOADING) - && (next_state != OSPF6_NEIGHBOR_EXCHANGE - && next_state != OSPF6_NEIGHBOR_LOADING)) + if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE || + prev_state == OSPF6_NEIGHBOR_LOADING) && + (next_state != OSPF6_NEIGHBOR_EXCHANGE && + next_state != OSPF6_NEIGHBOR_LOADING)) ospf6_maxage_remove(on->ospf6_if->area->ospf6); hook_call(ospf6_neighbor_change, on, next_state, prev_state); @@ -262,13 +287,14 @@ static void ospf6_neighbor_state_change(uint8_t next_state, /* RFC2328 section 10.4 */ static int need_adjacency(struct ospf6_neighbor *on) { - if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT - || on->ospf6_if->state == OSPF6_INTERFACE_DR - || on->ospf6_if->state == OSPF6_INTERFACE_BDR) + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT || + on->ospf6_if->state == OSPF6_INTERFACE_POINTTOMULTIPOINT || + on->ospf6_if->state == OSPF6_INTERFACE_DR || + on->ospf6_if->state == OSPF6_INTERFACE_BDR) return 1; - if (on->ospf6_if->drouter == on->router_id - || on->ospf6_if->bdrouter == on->router_id) + if (on->ospf6_if->drouter == on->router_id || + on->ospf6_if->bdrouter == on->router_id) return 1; return 0; @@ -422,13 +448,12 @@ void exchange_done(struct event *thread) /* Check loading state. */ void ospf6_check_nbr_loading(struct ospf6_neighbor *on) { - /* RFC2328 Section 10.9: When the neighbor responds to these requests with the proper Link State Update packet(s), the Link state request list is truncated and a new Link State Request packet is sent. */ - if ((on->state == OSPF6_NEIGHBOR_LOADING) - || (on->state == OSPF6_NEIGHBOR_EXCHANGE)) { + if ((on->state == OSPF6_NEIGHBOR_LOADING) || + (on->state == OSPF6_NEIGHBOR_EXCHANGE)) { if (on->request_list->count == 0) event_add_event(master, loading_done, on, 0, &on->event_loading_done); @@ -587,9 +612,8 @@ void inactivity_timer(struct event *thread) on->drouter = on->prev_drouter = 0; on->bdrouter = on->prev_bdrouter = 0; - ospf6_neighbor_state_change( - OSPF6_NEIGHBOR_DOWN, on, - OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER); + ospf6_neighbor_state_change(OSPF6_NEIGHBOR_DOWN, on, + OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER); event_add_event(master, neighbor_change, on->ospf6_if, 0, NULL); listnode_delete(on->ospf6_if->neighbor_list, on); @@ -597,9 +621,8 @@ void inactivity_timer(struct event *thread) } else { if (IS_DEBUG_OSPF6_GR) - zlog_debug( - "%s, Acting as HELPER for this neighbour, So restart the dead timer.", - __PRETTY_FUNCTION__); + zlog_debug("%s, Acting as HELPER for this neighbour, So restart the dead timer.", + __PRETTY_FUNCTION__); event_add_timer(master, inactivity_timer, on, on->ospf6_if->dead_interval, @@ -607,8 +630,224 @@ void inactivity_timer(struct event *thread) } } +/* P2P/P2MP stuff */ + +uint32_t ospf6_neighbor_cost(struct ospf6_neighbor *on) +{ + if (on->p2xp_cfg && on->p2xp_cfg->cfg_cost) + return on->p2xp_cfg->cost; + return on->ospf6_if->cost; +} + +static int ospf6_if_p2xp_neighcfg_cmp(const struct ospf6_if_p2xp_neighcfg *a, + const struct ospf6_if_p2xp_neighcfg *b) +{ + return IPV6_ADDR_CMP(&a->addr, &b->addr); +} + +struct ospf6_if_p2xp_neighcfg *ospf6_if_p2xp_find(struct ospf6_interface *oi, + const struct in6_addr *addr) +{ + struct ospf6_if_p2xp_neighcfg ref; + + if (!oi) + return NULL; + + ref.addr = *addr; + return ospf6_if_p2xp_neighcfgs_find(&oi->p2xp_neighs, &ref); +} + +static struct ospf6_if_p2xp_neighcfg * +ospf6_if_p2xp_get(struct ospf6_interface *oi, const struct in6_addr *addr) +{ + struct ospf6_if_p2xp_neighcfg ref, *ret; + + if (!oi) + return NULL; + + ref.addr = *addr; + ret = ospf6_if_p2xp_neighcfgs_find(&oi->p2xp_neighs, &ref); + if (!ret) { + ret = XCALLOC(MTYPE_OSPF6_NEIGHBOR_P2XP_CFG, sizeof(*ret)); + ret->addr = *addr; + ret->ospf6_if = oi; + + ospf6_if_p2xp_neighcfgs_add(&oi->p2xp_neighs, ret); + } + + return ret; +} + +static void ospf6_if_p2xp_destroy(struct ospf6_if_p2xp_neighcfg *p2xp_cfg) +{ + EVENT_OFF(p2xp_cfg->t_unicast_hello); + ospf6_if_p2xp_neighcfgs_del(&p2xp_cfg->ospf6_if->p2xp_neighs, p2xp_cfg); + + XFREE(MTYPE_OSPF6_NEIGHBOR_P2XP_CFG, p2xp_cfg); +} + +static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost) +{ + if (on->p2xp_cfg) + on->p2xp_cfg->active = NULL; + on->p2xp_cfg = ospf6_if_p2xp_find(on->ospf6_if, &on->linklocal_addr); + if (on->p2xp_cfg) + on->p2xp_cfg->active = on; + + if (ospf6_neighbor_cost(on) != prev_cost) + OSPF6_ROUTER_LSA_SCHEDULE(on->ospf6_if->area); +} /* vty functions */ + +#ifndef VTYSH_EXTRACT_PL +#include "ospf6d/ospf6_neighbor_clippy.c" +#endif + +DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X", + NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" + "Neighbor link-local address\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi = ifp->info; + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + + if (!oi) { + if (no) + return CMD_SUCCESS; + oi = ospf6_interface_create(ifp); + } + + if (no) { + struct ospf6_neighbor *on; + uint32_t prev_cost = 0; + + p2xp_cfg = ospf6_if_p2xp_find(oi, &neighbor); + if (!p2xp_cfg) + return CMD_SUCCESS; + + on = p2xp_cfg->active; + if (on) + prev_cost = ospf6_neighbor_cost(on); + + p2xp_cfg->active = NULL; + ospf6_if_p2xp_destroy(p2xp_cfg); + + if (on) { + on->p2xp_cfg = NULL; + p2xp_neigh_refresh(on, prev_cost); + } + return CMD_SUCCESS; + } + + (void)ospf6_if_p2xp_get(oi, &neighbor); + return CMD_SUCCESS; +} + +DEFPY(ipv6_ospf6_p2xp_neigh_cost, ipv6_ospf6_p2xp_neigh_cost_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)", + NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" + "Neighbor link-local address\n" + "Outgoing metric for this neighbor\n" + "Outgoing metric for this neighbor\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi = ifp->info; + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + uint32_t prev_cost = 0; + + if (!oi) { + if (no) + return CMD_SUCCESS; + oi = ospf6_interface_create(ifp); + } + + p2xp_cfg = ospf6_if_p2xp_get(oi, &neighbor); + + if (p2xp_cfg->active) + prev_cost = ospf6_neighbor_cost(p2xp_cfg->active); + + if (no) { + p2xp_cfg->cfg_cost = false; + p2xp_cfg->cost = 0; + } else { + p2xp_cfg->cfg_cost = true; + p2xp_cfg->cost = cost; + } + + if (p2xp_cfg->active) + p2xp_neigh_refresh(p2xp_cfg->active, prev_cost); + return CMD_SUCCESS; +} + +static void p2xp_unicast_hello_send(struct event *event); + +static void p2xp_unicast_hello_sched(struct ospf6_if_p2xp_neighcfg *p2xp_cfg) +{ + if (!p2xp_cfg->poll_interval || + (p2xp_cfg->ospf6_if->state != OSPF6_INTERFACE_POINTTOMULTIPOINT && + p2xp_cfg->ospf6_if->state != OSPF6_INTERFACE_POINTTOPOINT)) + /* state check covers DOWN state too */ + EVENT_OFF(p2xp_cfg->t_unicast_hello); + else + event_add_timer(master, p2xp_unicast_hello_send, p2xp_cfg, + p2xp_cfg->poll_interval, + &p2xp_cfg->t_unicast_hello); +} + +void ospf6_if_p2xp_up(struct ospf6_interface *oi) +{ + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + + frr_each (ospf6_if_p2xp_neighcfgs, &oi->p2xp_neighs, p2xp_cfg) + p2xp_unicast_hello_sched(p2xp_cfg); +} + +static void p2xp_unicast_hello_send(struct event *event) +{ + struct ospf6_if_p2xp_neighcfg *p2xp_cfg = EVENT_ARG(event); + struct ospf6_interface *oi = p2xp_cfg->ospf6_if; + + if (oi->state != OSPF6_INTERFACE_POINTTOPOINT && + oi->state != OSPF6_INTERFACE_POINTTOMULTIPOINT) + return; + + p2xp_unicast_hello_sched(p2xp_cfg); + + if (p2xp_cfg->active && p2xp_cfg->active->state >= OSPF6_NEIGHBOR_INIT) + return; + + ospf6_hello_send_addr(oi, &p2xp_cfg->addr); +} + +DEFPY(ipv6_ospf6_p2xp_neigh_poll_interval, + ipv6_ospf6_p2xp_neigh_poll_interval_cmd, + "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)", + NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n" + "Neighbor link-local address\n" + "Send unicast hellos to neighbor when down\n" + "Unicast hello interval when down (seconds)\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf6_interface *oi = ifp->info; + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + + if (!oi) { + if (no) + return CMD_SUCCESS; + oi = ospf6_interface_create(ifp); + } + if (no) + poll_interval = 0; + + p2xp_cfg = ospf6_if_p2xp_get(oi, &neighbor); + p2xp_cfg->poll_interval = poll_interval; + + p2xp_unicast_hello_sched(p2xp_cfg); + return CMD_SUCCESS; +} + /* show neighbor structure */ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on, json_object *json_array, bool use_json) @@ -631,8 +870,8 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on, /* Dead time */ h = m = s = 0; if (on->inactivity_timer) { - s = monotime_until(&on->inactivity_timer->u.sands, NULL) - / 1000000LL; + s = monotime_until(&on->inactivity_timer->u.sands, NULL) / + 1000000LL; h = s / 3600; s -= h * 3600; m = s / 60; @@ -643,6 +882,8 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on, /* Neighbor State */ if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT) snprintf(nstate, sizeof(nstate), "PointToPoint"); + else if (on->ospf6_if->type == OSPF_IFTYPE_POINTOMULTIPOINT) + snprintf(nstate, sizeof(nstate), "PtMultipoint"); else { if (on->router_id == on->drouter) snprintf(nstate, sizeof(nstate), "DR"); @@ -673,9 +914,9 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on, json_object_string_add(json_route, "duration", duration); json_object_string_add(json_route, "interfaceName", on->ospf6_if->interface->name); - json_object_string_add( - json_route, "interfaceState", - ospf6_interface_state_str[on->ospf6_if->state]); + json_object_string_add(json_route, "interfaceState", + ospf6_interface_state_str + [on->ospf6_if->state]); json_object_array_add(json_array, json_route); } else @@ -720,9 +961,9 @@ static void ospf6_neighbor_show_drchoice(struct vty *vty, json_object_string_add(json_route, "bdRouter", bdrouter); json_object_string_add(json_route, "interfaceName", on->ospf6_if->interface->name); - json_object_string_add( - json_route, "interfaceState", - ospf6_interface_state_str[on->ospf6_if->state]); + json_object_string_add(json_route, "interfaceState", + ospf6_interface_state_str + [on->ospf6_if->state]); json_object_array_add(json_array, json_route); } else @@ -777,9 +1018,8 @@ static void ospf6_neighbor_show_detail(struct vty *vty, (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " : ""), - (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) - ? "More" - : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More" + : ""), (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? "Master" : "Slave")); @@ -793,8 +1033,8 @@ static void ospf6_neighbor_show_detail(struct vty *vty, json_object_int_add(json_neighbor, "summaryListCount", on->summary_list->count); for (ALL_LSDB(on->summary_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "summaryListLsa", json_array); @@ -802,8 +1042,8 @@ static void ospf6_neighbor_show_detail(struct vty *vty, json_object_int_add(json_neighbor, "requestListCount", on->request_list->count); for (ALL_LSDB(on->request_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "requestListLsa", json_array); @@ -811,8 +1051,8 @@ static void ospf6_neighbor_show_detail(struct vty *vty, json_object_int_add(json_neighbor, "reTransListCount", on->retrans_list->count); for (ALL_LSDB(on->retrans_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "reTransListLsa", json_array); @@ -825,14 +1065,14 @@ static void ospf6_neighbor_show_detail(struct vty *vty, on->dbdesc_list->count); json_object_string_add(json_neighbor, "pendingLsaDbDescTime", duration); - json_object_string_add( - json_neighbor, "dbDescSendThread", - (event_is_scheduled(on->thread_send_dbdesc) ? "on" - : "off")); + json_object_string_add(json_neighbor, "dbDescSendThread", + (event_is_scheduled(on->thread_send_dbdesc) + ? "on" + : "off")); json_array = json_object_new_array(); for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "pendingLsaDbDesc", json_array); @@ -844,35 +1084,35 @@ static void ospf6_neighbor_show_detail(struct vty *vty, on->request_list->count); json_object_string_add(json_neighbor, "pendingLsaLsReqTime", duration); - json_object_string_add( - json_neighbor, "lsReqSendThread", - (event_is_scheduled(on->thread_send_lsreq) ? "on" - : "off")); + json_object_string_add(json_neighbor, "lsReqSendThread", + (event_is_scheduled(on->thread_send_lsreq) + ? "on" + : "off")); json_array = json_object_new_array(); for (ALL_LSDB(on->request_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "pendingLsaLsReq", json_array); timerclear(&res); if (event_is_scheduled(on->thread_send_lsupdate)) - timersub(&on->thread_send_lsupdate->u.sands, &now, - &res); + timersub(&on->thread_send_lsupdate->u.sands, &now, &res); timerstring(&res, duration, sizeof(duration)); json_object_int_add(json_neighbor, "pendingLsaLsUpdateCount", on->lsupdate_list->count); json_object_string_add(json_neighbor, "pendingLsaLsUpdateTime", duration); - json_object_string_add( - json_neighbor, "lsUpdateSendThread", - (event_is_scheduled(on->thread_send_lsupdate) ? "on" - : "off")); + json_object_string_add(json_neighbor, "lsUpdateSendThread", + (event_is_scheduled( + on->thread_send_lsupdate) + ? "on" + : "off")); json_array = json_object_new_array(); for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "pendingLsaLsUpdate", json_array); @@ -884,14 +1124,14 @@ static void ospf6_neighbor_show_detail(struct vty *vty, on->lsack_list->count); json_object_string_add(json_neighbor, "pendingLsaLsAckTime", duration); - json_object_string_add( - json_neighbor, "lsAckSendThread", - (event_is_scheduled(on->thread_send_lsack) ? "on" - : "off")); + json_object_string_add(json_neighbor, "lsAckSendThread", + (event_is_scheduled(on->thread_send_lsack) + ? "on" + : "off")); json_array = json_object_new_array(); for (ALL_LSDB(on->lsack_list, lsa, lsanext)) - json_object_array_add( - json_array, json_object_new_string(lsa->name)); + json_object_array_add(json_array, + json_object_new_string(lsa->name)); json_object_object_add(json_neighbor, "pendingLsaLsAck", json_array); @@ -900,36 +1140,36 @@ static void ospf6_neighbor_show_detail(struct vty *vty, if (on->auth_present == true) { json_object_string_add(json_neighbor, "authStatus", "enabled"); - json_object_int_add( - json_neighbor, "recvdHelloHigherSeqNo", - on->seqnum_h[OSPF6_MESSAGE_TYPE_HELLO]); - json_object_int_add( - json_neighbor, "recvdHelloLowerSeqNo", - on->seqnum_l[OSPF6_MESSAGE_TYPE_HELLO]); - json_object_int_add( - json_neighbor, "recvdDBDescHigherSeqNo", - on->seqnum_h[OSPF6_MESSAGE_TYPE_DBDESC]); - json_object_int_add( - json_neighbor, "recvdDBDescLowerSeqNo", - on->seqnum_l[OSPF6_MESSAGE_TYPE_DBDESC]); - json_object_int_add( - json_neighbor, "recvdLSReqHigherSeqNo", - on->seqnum_h[OSPF6_MESSAGE_TYPE_LSREQ]); - json_object_int_add( - json_neighbor, "recvdLSReqLowerSeqNo", - on->seqnum_l[OSPF6_MESSAGE_TYPE_LSREQ]); - json_object_int_add( - json_neighbor, "recvdLSUpdHigherSeqNo", - on->seqnum_h[OSPF6_MESSAGE_TYPE_LSUPDATE]); - json_object_int_add( - json_neighbor, "recvdLSUpdLowerSeqNo", - on->seqnum_l[OSPF6_MESSAGE_TYPE_LSUPDATE]); - json_object_int_add( - json_neighbor, "recvdLSAckHigherSeqNo", - on->seqnum_h[OSPF6_MESSAGE_TYPE_LSACK]); - json_object_int_add( - json_neighbor, "recvdLSAckLowerSeqNo", - on->seqnum_l[OSPF6_MESSAGE_TYPE_LSACK]); + json_object_int_add(json_neighbor, + "recvdHelloHigherSeqNo", + on->seqnum_h[OSPF6_MESSAGE_TYPE_HELLO]); + json_object_int_add(json_neighbor, + "recvdHelloLowerSeqNo", + on->seqnum_l[OSPF6_MESSAGE_TYPE_HELLO]); + json_object_int_add(json_neighbor, + "recvdDBDescHigherSeqNo", + on->seqnum_h[OSPF6_MESSAGE_TYPE_DBDESC]); + json_object_int_add(json_neighbor, + "recvdDBDescLowerSeqNo", + on->seqnum_l[OSPF6_MESSAGE_TYPE_DBDESC]); + json_object_int_add(json_neighbor, + "recvdLSReqHigherSeqNo", + on->seqnum_h[OSPF6_MESSAGE_TYPE_LSREQ]); + json_object_int_add(json_neighbor, + "recvdLSReqLowerSeqNo", + on->seqnum_l[OSPF6_MESSAGE_TYPE_LSREQ]); + json_object_int_add(json_neighbor, + "recvdLSUpdHigherSeqNo", + on->seqnum_h[OSPF6_MESSAGE_TYPE_LSUPDATE]); + json_object_int_add(json_neighbor, + "recvdLSUpdLowerSeqNo", + on->seqnum_l[OSPF6_MESSAGE_TYPE_LSUPDATE]); + json_object_int_add(json_neighbor, + "recvdLSAckHigherSeqNo", + on->seqnum_h[OSPF6_MESSAGE_TYPE_LSACK]); + json_object_int_add(json_neighbor, + "recvdLSAckLowerSeqNo", + on->seqnum_l[OSPF6_MESSAGE_TYPE_LSACK]); } else json_object_string_add(json_neighbor, "authStatus", "disabled"); @@ -951,9 +1191,8 @@ static void ospf6_neighbor_show_detail(struct vty *vty, (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " : ""), - (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) - ? "More " - : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " + : ""), (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? "Master" : "Slave"), @@ -1000,8 +1239,7 @@ static void ospf6_neighbor_show_detail(struct vty *vty, timerclear(&res); if (event_is_scheduled(on->thread_send_lsupdate)) - timersub(&on->thread_send_lsupdate->u.sands, &now, - &res); + timersub(&on->thread_send_lsupdate->u.sands, &now, &res); timerstring(&res, duration, sizeof(duration)); vty_out(vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", @@ -1141,8 +1379,7 @@ DEFUN(show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd, static int ospf6_neighbor_show_common(struct vty *vty, int argc, struct cmd_token **argv, - struct ospf6 *ospf6, int idx_ipv4, - bool uj) + struct ospf6 *ospf6, int idx_ipv4, bool uj) { struct ospf6_neighbor *on; struct ospf6_interface *oi; @@ -1214,16 +1451,18 @@ void ospf6_neighbor_init(void) { install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd); install_element(VIEW_NODE, &show_ipv6_ospf6_neighbor_one_cmd); + + install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_neigh_cmd); + install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_neigh_cost_cmd); + install_element(INTERFACE_NODE, + &ipv6_ospf6_p2xp_neigh_poll_interval_cmd); } -DEFUN (debug_ospf6_neighbor, - debug_ospf6_neighbor_cmd, - "debug ospf6 neighbor []", - DEBUG_STR - OSPF6_STR - "Debug OSPFv3 Neighbor\n" - "Debug OSPFv3 Neighbor State Change\n" - "Debug OSPFv3 Neighbor Event\n") +DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd, + "debug ospf6 neighbor []", + DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n" + "Debug OSPFv3 Neighbor State Change\n" + "Debug OSPFv3 Neighbor Event\n") { int idx_type = 3; unsigned char level = 0; @@ -1241,15 +1480,11 @@ DEFUN (debug_ospf6_neighbor, } -DEFUN (no_debug_ospf6_neighbor, - no_debug_ospf6_neighbor_cmd, - "no debug ospf6 neighbor []", - NO_STR - DEBUG_STR - OSPF6_STR - "Debug OSPFv3 Neighbor\n" - "Debug OSPFv3 Neighbor State Change\n" - "Debug OSPFv3 Neighbor Event\n") +DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd, + "no debug ospf6 neighbor []", + NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n" + "Debug OSPFv3 Neighbor State Change\n" + "Debug OSPFv3 Neighbor Event\n") { int idx_type = 4; unsigned char level = 0; @@ -1267,12 +1502,8 @@ DEFUN (no_debug_ospf6_neighbor, } -DEFUN (no_debug_ospf6, - no_debug_ospf6_cmd, - "no debug ospf6", - NO_STR - DEBUG_STR - OSPF6_STR) +DEFUN(no_debug_ospf6, no_debug_ospf6_cmd, "no debug ospf6", + NO_STR DEBUG_STR OSPF6_STR) { unsigned int i; @@ -1287,12 +1518,11 @@ DEFUN (no_debug_ospf6, ospf6_lsa_debug_set_all(false); for (i = 0; i < 6; i++) - OSPF6_DEBUG_MESSAGE_OFF(i, - OSPF6_DEBUG_NEIGHBOR_STATE - | OSPF6_DEBUG_NEIGHBOR_EVENT); + OSPF6_DEBUG_MESSAGE_OFF(i, OSPF6_DEBUG_NEIGHBOR_STATE | + OSPF6_DEBUG_NEIGHBOR_EVENT); - OSPF6_DEBUG_NEIGHBOR_OFF(OSPF6_DEBUG_NEIGHBOR_STATE - | OSPF6_DEBUG_NEIGHBOR_EVENT); + OSPF6_DEBUG_NEIGHBOR_OFF(OSPF6_DEBUG_NEIGHBOR_STATE | + OSPF6_DEBUG_NEIGHBOR_EVENT); OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_TABLE); OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTRA); OSPF6_DEBUG_ROUTE_OFF(OSPF6_DEBUG_ROUTE_INTER); @@ -1316,6 +1546,25 @@ int config_write_ospf6_debug_neighbor(struct vty *vty) return 0; } +int config_write_ospf6_p2xp_neighbor(struct vty *vty, struct ospf6_interface *oi) +{ + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + + frr_each (ospf6_if_p2xp_neighcfgs, &oi->p2xp_neighs, p2xp_cfg) { + vty_out(vty, " ipv6 ospf6 neighbor %pI6\n", &p2xp_cfg->addr); + + if (p2xp_cfg->poll_interval) + vty_out(vty, + " ipv6 ospf6 neighbor %pI6 poll-interval %u\n", + &p2xp_cfg->addr, p2xp_cfg->poll_interval); + + if (p2xp_cfg->cfg_cost) + vty_out(vty, " ipv6 ospf6 neighbor %pI6 cost %u\n", + &p2xp_cfg->addr, p2xp_cfg->cost); + } + return 0; +} + void install_element_ospf6_debug_neighbor(void) { install_element(ENABLE_NODE, &debug_ospf6_neighbor_cmd); diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index 226f4c1..60a7621 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -6,8 +6,11 @@ #ifndef OSPF6_NEIGHBOR_H #define OSPF6_NEIGHBOR_H +#include "typesafe.h" #include "hook.h" +#include "ospf6_message.h" + /* Forward declaration(s). */ struct ospf6_area; @@ -52,6 +55,8 @@ struct ospf6_helper_info { uint32_t rejected_reason; }; +struct ospf6_if_p2xp_neighcfg; + /* Neighbor structure */ struct ospf6_neighbor { /* Neighbor Router ID String */ @@ -60,6 +65,11 @@ struct ospf6_neighbor { /* OSPFv3 Interface this neighbor belongs to */ struct ospf6_interface *ospf6_if; + /* P2P/P2MP config for this neighbor. + * can be NULL if not explicitly configured! + */ + struct ospf6_if_p2xp_neighcfg *p2xp_cfg; + /* Neighbor state */ uint8_t state; @@ -190,6 +200,14 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, struct ospf6_interface *oi); void ospf6_neighbor_delete(struct ospf6_neighbor *on); +void ospf6_neighbor_lladdr_set(struct ospf6_neighbor *on, + const struct in6_addr *addr); +struct ospf6_if_p2xp_neighcfg *ospf6_if_p2xp_find(struct ospf6_interface *oi, + const struct in6_addr *addr); +void ospf6_if_p2xp_up(struct ospf6_interface *oi); + +uint32_t ospf6_neighbor_cost(struct ospf6_neighbor *on); + /* Neighbor event */ extern void hello_received(struct event *thread); extern void twoway_received(struct event *thread); @@ -205,6 +223,8 @@ extern void ospf6_check_nbr_loading(struct ospf6_neighbor *on); extern void ospf6_neighbor_init(void); extern int config_write_ospf6_debug_neighbor(struct vty *vty); +extern int config_write_ospf6_p2xp_neighbor(struct vty *vty, + struct ospf6_interface *oi); extern void install_element_ospf6_debug_neighbor(void); DECLARE_HOOK(ospf6_neighbor_change, diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 4430329..10a1208 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -363,7 +363,7 @@ void ospf6_route_zebra_copy_nexthops(struct ospf6_route *route, case NEXTHOP_TYPE_IPV6_IFINDEX: nexthops[i].ifindex = nh->ifindex; - /* FALLTHROUGH */ + fallthrough; case NEXTHOP_TYPE_IPV6: nexthops[i].gate.ipv6 = nh->address; break; @@ -540,6 +540,10 @@ int ospf6_route_cmp(struct ospf6_route *ra, struct ospf6_route *rb) if (ra->path.area_id != rb->path.area_id) return (ntohl(ra->path.area_id) - ntohl(rb->path.area_id)); + if ((ra->prefix_options & OSPF6_PREFIX_OPTION_LA) + != (rb->prefix_options & OSPF6_PREFIX_OPTION_LA)) + return ra->prefix_options & OSPF6_PREFIX_OPTION_LA ? -1 : 1; + return 0; } diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index c212595..2c1d17e 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -67,7 +67,7 @@ static inline bool ospf6_nexthop_is_same(const struct ospf6_nexthop *nha, case NEXTHOP_TYPE_IPV6_IFINDEX: if (nha->ifindex != nhb->ifindex) return false; - /* FALLTHROUGH */ + fallthrough; case NEXTHOP_TYPE_IPV6: if (!IN6_ARE_ADDR_EQUAL(&nha->address, &nhb->address)) return false; diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index f88667b..17cdcda 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -697,8 +697,8 @@ static uint8_t *ospfv3GeneralGroup(struct variable *v, oid *name, case OSPFv3REFERENCEBANDWIDTH: if (ospf6) return SNMP_INTEGER(ospf6->ref_bandwidth); - /* Otherwise, like for "not implemented". */ - /* fallthru */ + /* Otherwise, like for "not implemented". */ + return NULL; case OSPFv3RESTARTSUPPORT: case OSPFv3RESTARTINTERVAL: case OSPFv3RESTARTSTRICTLSACHECKING: @@ -1126,6 +1126,8 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length, return SNMP_INTEGER(1); else if (oi->type == OSPF_IFTYPE_POINTOPOINT) return SNMP_INTEGER(3); + else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) + return SNMP_INTEGER(5); else break; /* Unknown, don't put anything */ case OSPFv3IFADMINSTATUS: @@ -1367,6 +1369,7 @@ static int ospf6TrapIfStateChange(struct ospf6_interface *oi, int next_state, /* Terminal state or regression */ if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) + && (next_state != OSPF6_INTERFACE_POINTTOMULTIPOINT) && (next_state != OSPF6_INTERFACE_DROTHER) && (next_state != OSPF6_INTERFACE_BDR) && (next_state != OSPF6_INTERFACE_DR) && (next_state >= prev_state)) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 216837d..a3fb205 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -16,6 +16,7 @@ #include "defaults.h" #include "lib/json.h" #include "lib_errors.h" +#include "frrdistance.h" #include "ospf6_proto.h" #include "ospf6_message.h" @@ -429,17 +430,7 @@ static struct ospf6 *ospf6_create(const char *name) /* Make ospf protocol socket. */ ospf6_serv_sock(o); - /* If sequence number is stored in persistent storage, read it. - */ - if (ospf6_auth_nvm_file_exist() == OSPF6_AUTH_FILE_EXIST) { - ospf6_auth_seqno_nvm_read(o); - o->seqnum_h = o->seqnum_h + 1; - ospf6_auth_seqno_nvm_update(o); - } else { - o->seqnum_l = o->seqnum_h = 0; - ospf6_auth_seqno_nvm_update(o); - } - + ospf6_auth_init(o); return o; } @@ -485,6 +476,7 @@ void ospf6_delete(struct ospf6 *o) struct ospf6_area *oa; struct vrf *vrf; struct ospf6_external_aggr_rt *aggr; + uint32_t i; QOBJ_UNREG(o); @@ -531,6 +523,13 @@ void ospf6_delete(struct ospf6 *o) } route_table_finish(o->rt_aggr_tbl); + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + if (!o->redist[i]) + continue; + + list_delete(&o->redist[i]); + } + XFREE(MTYPE_OSPF6_TOP, o->name); XFREE(MTYPE_OSPF6_TOP, o); } @@ -575,6 +574,11 @@ void ospf6_master_init(struct event_loop *master) om6->master = master; } +void ospf6_master_delete(void) +{ + list_delete(&om6->ospf6); +} + static void ospf6_maxage_remover(struct event *thread) { struct ospf6 *o = (struct ospf6 *)EVENT_ARG(thread); @@ -1056,148 +1060,6 @@ DEFUN (no_ospf6_distance_ospf6, return CMD_SUCCESS; } -DEFUN_HIDDEN (ospf6_interface_area, - ospf6_interface_area_cmd, - "interface IFNAME area ", - "Enable routing on an IPv6 interface\n" - IFNAME_STR - "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n" - ) -{ - VTY_DECLVAR_CONTEXT(ospf6, ospf6); - int idx_ifname = 1; - int idx_ipv4 = 3; - struct ospf6_area *oa; - struct ospf6_interface *oi; - struct interface *ifp; - uint32_t area_id; - int format; - - vty_out(vty, - "This command is deprecated, because it is not VRF-aware.\n"); - vty_out(vty, - "Please, use \"ipv6 ospf6 area\" on an interface instead.\n"); - - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) - oi = ospf6_interface_create(ifp); - if (oi->area) { - vty_out(vty, "%s already attached to Area %s\n", - oi->interface->name, oi->area->name); - return CMD_SUCCESS; - } - - if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) { - vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg); - return CMD_WARNING_CONFIG_FAILED; - } - - oi->area_id = area_id; - oi->area_id_format = format; - - oa = ospf6_area_lookup(area_id, ospf6); - if (oa == NULL) - oa = ospf6_area_create(area_id, ospf6, format); - - /* attach interface to area */ - listnode_add(oa->if_list, oi); /* sort ?? */ - oi->area = oa; - - SET_FLAG(oa->flag, OSPF6_AREA_ENABLE); - - /* ospf6 process is currently disabled, not much more to do */ - if (CHECK_FLAG(ospf6->flag, OSPF6_DISABLED)) - return CMD_SUCCESS; - - /* start up */ - ospf6_interface_enable(oi); - - /* If the router is ABR, originate summary routes */ - if (ospf6_check_and_set_router_abr(ospf6)) { - ospf6_abr_enable_area(oa); - ospf6_schedule_abr_task(oa->ospf6); - } - - return CMD_SUCCESS; -} - -DEFUN_HIDDEN (no_ospf6_interface_area, - no_ospf6_interface_area_cmd, - "no interface IFNAME area ", - NO_STR - "Disable routing on an IPv6 interface\n" - IFNAME_STR - "Specify the OSPF6 area ID\n" - "OSPF6 area ID in IPv4 address notation\n" - "OSPF6 area ID in decimal notation\n" - ) -{ - VTY_DECLVAR_CONTEXT(ospf6, ospf6); - int idx_ifname = 2; - int idx_ipv4 = 4; - struct ospf6_interface *oi; - struct ospf6_area *oa; - struct interface *ifp; - uint32_t area_id; - - vty_out(vty, - "This command is deprecated, because it is not VRF-aware.\n"); - vty_out(vty, - "Please, use \"no ipv6 ospf6 area\" on an interface instead.\n"); - - /* find/create ospf6 interface */ - ifp = if_get_by_name(argv[idx_ifname]->arg, ospf6->vrf_id, ospf6->name); - - if (ifp == NULL) { - vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg); - return CMD_SUCCESS; - } - - oi = (struct ospf6_interface *)ifp->info; - if (oi == NULL) { - vty_out(vty, "Interface %s not enabled\n", ifp->name); - return CMD_SUCCESS; - } - - /* parse Area-ID */ - if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) - area_id = htonl(strtoul(argv[idx_ipv4]->arg, NULL, 10)); - - /* Verify Area */ - if (oi->area == NULL) { - vty_out(vty, "%s not attached to area %s\n", - oi->interface->name, argv[idx_ipv4]->arg); - return CMD_SUCCESS; - } - - if (oi->area->area_id != area_id) { - vty_out(vty, "Wrong Area-ID: %s is attached to area %s\n", - oi->interface->name, oi->area->name); - return CMD_SUCCESS; - } - - ospf6_interface_disable(oi); - - oa = oi->area; - listnode_delete(oi->area->if_list, oi); - oi->area = (struct ospf6_area *)NULL; - - /* Withdraw inter-area routes from this area, if necessary */ - if (oa->if_list->count == 0) { - UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE); - ospf6_abr_disable_area(oa); - } - - oi->area_id = 0; - oi->area_id_format = OSPF6_AREA_FMT_UNSET; - - return CMD_SUCCESS; -} - DEFUN (ospf6_stub_router_admin, ospf6_stub_router_admin_cmd, "stub-router administrative", @@ -2346,8 +2208,6 @@ void ospf6_top_init(void) install_element(OSPF6_NODE, &ospf6_timers_lsa_cmd); install_element(OSPF6_NODE, &no_ospf6_timers_lsa_cmd); - install_element(OSPF6_NODE, &ospf6_interface_area_cmd); - install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd); install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd); install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd); diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index a38dad8..8288413 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -236,6 +236,8 @@ extern struct ospf6_master *om6; /* prototypes */ extern void ospf6_master_init(struct event_loop *master); +extern void ospf6_master_delete(void); + extern void install_element_ospf6_clear_process(void); extern void ospf6_top_init(void); extern void ospf6_delete(struct ospf6 *o); diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 8bd0d8f..3245578 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -147,30 +147,22 @@ void ospf6_zebra_import_default_route(struct ospf6 *ospf6, bool unreg) __func__); } -static int ospf6_zebra_import_check_update(ZAPI_CALLBACK_ARGS) +static void ospf6_zebra_import_check_update(struct vrf *vrf, + struct prefix *matched, + struct zapi_route *nhr) { struct ospf6 *ospf6; - struct zapi_route nhr; - struct prefix matched; - ospf6 = ospf6_lookup_by_vrf_id(vrf_id); + ospf6 = (struct ospf6 *)vrf->info; if (ospf6 == NULL || !IS_OSPF6_ASBR(ospf6)) - return 0; - - if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) { - zlog_err("%s[%u]: Failure to decode route", __func__, - ospf6->vrf_id); - return -1; - } + return; - if (matched.family != AF_INET6 || matched.prefixlen != 0 || - nhr.type == ZEBRA_ROUTE_OSPF6) - return 0; + if (matched->family != AF_INET6 || matched->prefixlen != 0 || + nhr->type == ZEBRA_ROUTE_OSPF6) + return; - ospf6->nssa_default_import_check.status = !!nhr.nexthop_num; + ospf6->nssa_default_import_check.status = !!nhr->nexthop_num; ospf6_abr_nssa_type_7_defaults(ospf6); - - return 0; } static int ospf6_zebra_if_address_update_add(ZAPI_CALLBACK_ARGS) @@ -763,7 +755,6 @@ static zclient_handler *const ospf6_handlers[] = { [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf6_zebra_if_address_update_delete, [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf6_zebra_read_route, [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf6_zebra_read_route, - [ZEBRA_NEXTHOP_UPDATE] = ospf6_zebra_import_check_update, }; void ospf6_zebra_init(struct event_loop *master) @@ -773,6 +764,7 @@ void ospf6_zebra_init(struct event_loop *master) array_size(ospf6_handlers)); zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs); zclient->zebra_connected = ospf6_zebra_connected; + zclient->nexthop_update = ospf6_zebra_import_check_update; /* Install command element for zebra node. */ install_element(VIEW_NODE, &show_ospf6_zebra_cmd); diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index f6d27c8..5f89af9 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -83,8 +83,10 @@ clippy_scan += \ ospf6d/ospf6_lsa.c \ ospf6d/ospf6_gr_helper.c \ ospf6d/ospf6_gr.c \ + ospf6d/ospf6_interface.c \ ospf6d/ospf6_nssa.c \ ospf6d/ospf6_route.c \ + ospf6d/ospf6_neighbor.c \ # end nodist_ospf6d_ospf6d_SOURCES = \ -- cgit v1.2.3