diff --git a/ospfd/.gitignore b/ospfd/.gitignore index 752c875a62..018a363a93 100644 --- a/ospfd/.gitignore +++ b/ospfd/.gitignore @@ -15,3 +15,4 @@ TAGS *~ *.loT *.a +*.clippy.c diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c index 968461b4d0..f7aa94ad18 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -91,7 +91,7 @@ static void ospf_area_range_delete(struct ospf_area *area, struct ospf_area_range *range = rn->info; if (range->specifics != 0) - ospf_delete_discard_route(area->ospf->new_table, + ospf_delete_discard_route(area->ospf, area->ospf->new_table, (struct prefix_ipv4 *)&rn->p); ospf_area_range_free(range); @@ -1684,12 +1684,12 @@ static void ospf_abr_manage_discard_routes(struct ospf *ospf) if (CHECK_FLAG(range->flags, OSPF_AREA_RANGE_ADVERTISE)) { if (range->specifics) - ospf_add_discard_route( + ospf_add_discard_route(ospf, ospf->new_table, area, (struct prefix_ipv4 *)&rn->p); else - ospf_delete_discard_route( + ospf_delete_discard_route(ospf, ospf->new_table, (struct prefix_ipv4 *)&rn->p); diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index a5f5971ac0..252a5df0fd 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -80,9 +80,10 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_addr(struct in_addr address) { struct listnode *node, *nnode; struct ospf_interface *oi; - struct ospf *ospf; + struct ospf *ospf = NULL; - if (!(ospf = ospf_lookup())) + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (!ospf) return NULL; for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) @@ -97,9 +98,10 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp) { struct listnode *node, *nnode; struct ospf_interface *oi; - struct ospf *ospf; + struct ospf *ospf = NULL; - if (!(ospf = ospf_lookup())) + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (!ospf) return NULL; for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) @@ -999,7 +1001,7 @@ void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv) struct ospf_interface *oi; struct registered_opaque_type *r; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) { /* Check if this interface is indeed ready for type 9 */ @@ -1047,7 +1049,7 @@ void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv) struct ospf *ospf; struct ospf_area *area; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { struct registered_opaque_type *r; @@ -1094,7 +1096,7 @@ void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv) struct ospf *ospf; struct registered_opaque_type *r; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Can type 11 be originated? */ if (!ospf_apiserver_is_ready_type11(ospf)) @@ -1271,7 +1273,7 @@ int ospf_apiserver_handle_sync_lsdb(struct ospf_apiserver *apiserv, struct ospf *ospf; struct ospf_area *area; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Get request sequence number */ seqnum = msg_get_seq(msg); @@ -1374,7 +1376,11 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area, struct ospf *ospf; - ospf = ospf_lookup(); + if (oi && oi->ospf) + ospf = oi->ospf; + else + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + assert(ospf); /* Create a stream for internal opaque LSA */ @@ -1429,6 +1435,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area, new->area = area; new->oi = oi; + new->vrf_id = ospf->vrf_id; SET_FLAG(new->flags, OSPF_LSA_SELF); memcpy(new->data, newlsa, length); @@ -1497,7 +1504,7 @@ int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv, int ready = 0; int rc = 0; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Extract opaque LSA data from message */ omsg = (struct msg_originate_request *)STREAM_DATA(msg->s); @@ -1640,7 +1647,7 @@ void ospf_apiserver_flood_opaque_lsa(struct ospf_lsa *lsa) case OSPF_OPAQUE_AS_LSA: { struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); assert(ospf); /* Increment counters? XXX */ @@ -1656,7 +1663,7 @@ int ospf_apiserver_originate1(struct ospf_lsa *lsa) { struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); assert(ospf); /* Install this LSA into LSDB. */ @@ -1726,7 +1733,7 @@ struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa) struct ospf_lsa *new = NULL; struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); assert(ospf); apiserv = lookup_apiserver_by_lsa(lsa); @@ -1810,7 +1817,7 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, int rc = 0; struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); assert(ospf); /* Extract opaque LSA from message */ @@ -1862,7 +1869,7 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv, * the LSDB until it is finally handled by the maxage remover thread. * Therefore, the lookup function below may return non-NULL result. */ - old = ospf_lsa_lookup(area, dmsg->lsa_type, id, ospf->router_id); + old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id); if (!old) { zlog_warn( "ospf_apiserver_lsa_delete: LSA[Type%d:%s] not in LSDB", @@ -1923,7 +1930,7 @@ void ospf_apiserver_flush_opaque_lsa(struct ospf_apiserver *apiserv, struct ospf *ospf; struct ospf_area *area; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); assert(ospf); /* Set parameter struct. */ diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index e3b66d597b..89c462693b 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -58,7 +58,8 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p) /* Remove route from zebra. */ if (or->type == OSPF_DESTINATION_NETWORK) - ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, + ospf_zebra_delete(ospf, + (struct prefix_ipv4 *)&rn->p, or); ospf_route_free(or); diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index bf2b809ddc..877e4b7fb0 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -598,7 +598,8 @@ static int ospf_ase_route_match_same(struct route_table *rt, return 1; } -static int ospf_ase_compare_tables(struct route_table *new_external_route, +static int ospf_ase_compare_tables(struct ospf *ospf, + struct route_table *new_external_route, struct route_table *old_external_route) { struct route_node *rn, *new_rn; @@ -609,7 +610,8 @@ static int ospf_ase_compare_tables(struct route_table *new_external_route, if ((or = rn->info)) { if (!(new_rn = route_node_lookup(new_external_route, &rn->p))) - ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, + ospf_zebra_delete(ospf, + (struct prefix_ipv4 *)&rn->p, or); else route_unlock_node(new_rn); @@ -621,7 +623,8 @@ static int ospf_ase_compare_tables(struct route_table *new_external_route, if ((or = rn->info) != NULL) if (!ospf_ase_route_match_same(old_external_route, &rn->p, or)) - ospf_zebra_add((struct prefix_ipv4 *)&rn->p, + ospf_zebra_add(ospf, + (struct prefix_ipv4 *)&rn->p, or); return 0; @@ -666,7 +669,7 @@ static int ospf_ase_calculate_timer(struct thread *t) /* Compare old and new external routing table and install the difference info zebra/kernel */ - ospf_ase_compare_tables(ospf->new_external_route, + ospf_ase_compare_tables(ospf, ospf->new_external_route, ospf->old_external_route); /* Delete old external routing table */ @@ -814,7 +817,7 @@ void ospf_ase_incremental_update(struct ospf *ospf, struct ospf_lsa *lsa) } /* install changes to zebra */ - ospf_ase_compare_tables(ospf->new_external_route, tmp_old); + ospf_ase_compare_tables(ospf, ospf->new_external_route, tmp_old); /* update ospf->old_external_route table */ if (rn && rn->info) diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index 6d07b44364..9254e7d240 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -75,12 +75,13 @@ static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor *nbr, int command) bfd_info = (struct bfd_info *)params->bfd_info; if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) - zlog_debug("%s nbr (%s) with BFD", + zlog_debug("%s nbr (%s) with BFD. OSPF vrf %s", bfd_get_command_dbg_str(command), - inet_ntoa(nbr->src)); + inet_ntoa(nbr->src), + ospf_vrf_id_to_name(oi->ospf->vrf_id)); bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->src, NULL, ifp->name, - 0, 0, command, 0, VRF_DEFAULT); + 0, 0, command, 0, oi->ospf->vrf_id); } /* @@ -158,7 +159,7 @@ static int ospf_bfd_nbr_replay(int command, struct zclient *zclient, /* Send the client registration */ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); - /* Replay the neighbor, if BFD is enabled in BGP */ + /* Replay the neighbor, if BFD is enabled in OSPF */ for (ALL_LIST_ELEMENTS(om->ospf, node, onode, ospf)) { for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, inode, oi)) { if ((nbrs = oi->nbrs) == NULL) diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index 619bd4e5f5..eca0f85f57 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -1604,9 +1604,10 @@ DEFUN_NOSH (show_debugging_ospf, DEBUG_STR OSPF_STR) { - struct ospf *ospf; + struct ospf *ospf = NULL; - if ((ospf = ospf_lookup()) == NULL) + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL) return CMD_SUCCESS; return show_debugging_ospf_common(vty, ospf); @@ -1651,7 +1652,8 @@ static int config_write_debug(struct vty *vty) char str[16]; memset(str, 0, 16); - if ((ospf = ospf_lookup()) == NULL) + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL) return CMD_SUCCESS; if (ospf->instance) diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index c775f2ea2e..aac2f3ee92 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -77,7 +77,8 @@ static void ospf_flood_delayed_lsa_ack(struct ospf_neighbor *inbr, } /* Check LSA is related to external info. */ -struct external_info *ospf_external_info_check(struct ospf_lsa *lsa) +struct external_info *ospf_external_info_check(struct ospf *ospf, + struct ospf_lsa *lsa) { struct as_external_lsa *al; struct prefix_ipv4 p; @@ -96,11 +97,11 @@ struct external_info *ospf_external_info_check(struct ospf_lsa *lsa) redist_on = is_prefix_default(&p) ? vrf_bitmap_check(zclient->default_information, - VRF_DEFAULT) + ospf->vrf_id) : (zclient->mi_redist[AFI_IP][type].enabled || vrf_bitmap_check( zclient->redist[AFI_IP][type], - VRF_DEFAULT)); + ospf->vrf_id)); // Pending: check for MI above. if (redist_on) { struct list *ext_list; @@ -205,7 +206,7 @@ static void ospf_process_self_originated_lsa(struct ospf *ospf, ospf_translated_nssa_refresh(ospf, NULL, new); return; } - ei = ospf_external_info_check(new); + ei = ospf_external_info_check(ospf, new); if (ei) ospf_external_lsa_refresh(ospf, new, ei, LSA_REFRESH_FORCE); diff --git a/ospfd/ospf_flood.h b/ospfd/ospf_flood.h index b74894567d..6f7ecfccf0 100644 --- a/ospfd/ospf_flood.h +++ b/ospfd/ospf_flood.h @@ -61,7 +61,8 @@ extern void ospf_flood_lsa_as(struct ospf_lsa *); extern void ospf_lsa_flush_area(struct ospf_lsa *, struct ospf_area *); extern void ospf_lsa_flush_as(struct ospf *, struct ospf_lsa *); extern void ospf_lsa_flush(struct ospf *, struct ospf_lsa *); -extern struct external_info *ospf_external_info_check(struct ospf_lsa *); +extern struct external_info *ospf_external_info_check(struct ospf *, + struct ospf_lsa *); extern void ospf_lsdb_init(struct ospf_lsdb *); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 422e1a2a6b..d8d7caa688 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -243,6 +243,11 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp, oi->ospf = ospf; QOBJ_REG(oi, ospf_interface); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ospf interface %s vrf %s id %u created", + __PRETTY_FUNCTION__, ifp->name, + ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id); + return oi; } @@ -313,6 +318,12 @@ void ospf_if_free(struct ospf_interface *oi) list_free(oi->ls_ack); list_free(oi->ls_ack_direct.ls_ack); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ospf interface %s vrf %s id %u deleted", + __PRETTY_FUNCTION__, oi->ifp->name, + ospf_vrf_id_to_name(oi->ifp->vrf_id), + oi->ifp->vrf_id); + ospf_delete_from_if(oi->ifp, oi); listnode_delete(oi->ospf->oiflist, oi); @@ -335,7 +346,11 @@ struct ospf_interface *ospf_if_exists(struct ospf_interface *oic) struct ospf *ospf; struct ospf_interface *oi; - if ((ospf = ospf_lookup()) == NULL) + if (!oic) + return NULL; + + ospf = oic->ospf; + if (ospf == NULL) return NULL; for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) @@ -800,10 +815,11 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf, } if (IS_DEBUG_OSPF_EVENT) - zlog_debug("ospf_vl_new(): creating pseudo zebra interface"); + zlog_debug("ospf_vl_new(): creating pseudo zebra interface vrf id %u", + ospf->vrf_id); snprintf(ifname, sizeof(ifname), "VLINK%d", vlink_count); - vi = if_create(ifname, strnlen(ifname, sizeof(ifname)), VRF_DEFAULT); + vi = if_create(ifname, strnlen(ifname, sizeof(ifname)), ospf->vrf_id); /* * if_create sets ZEBRA_INTERFACE_LINKDETECTION * virtual links don't need this. @@ -1164,7 +1180,6 @@ u_char ospf_default_iftype(struct interface *ifp) void ospf_if_init() { /* Initialize Zebra interface data structure. */ - om->iflist = vrf_iflist(VRF_DEFAULT); hook_register_prio(if_add, 0, ospf_if_new_hook); hook_register_prio(if_del, 0, ospf_if_delete_hook); } diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index fa13843764..e5d4d34231 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -161,6 +161,7 @@ struct ospf_lsa *ospf_lsa_new() monotime(&new->tv_recv); new->tv_orig = new->tv_recv; new->refresh_list = -1; + new->vrf_id = VRF_DEFAULT; return new; } @@ -786,6 +787,7 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area) new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + new->vrf_id = area->ospf->vrf_id; /* Copy LSA data to store, discard stream. */ new->data = ospf_lsa_data_new(length); @@ -1001,6 +1003,7 @@ static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi) new->area = oi->area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + new->vrf_id = oi->ospf->vrf_id; /* Copy LSA to store. */ new->data = ospf_lsa_data_new(length); @@ -1180,6 +1183,7 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area, new = ospf_lsa_new(); new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + new->vrf_id = area->ospf->vrf_id; /* Copy LSA to store. */ new->data = ospf_lsa_data_new(length); @@ -1321,6 +1325,7 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area, new = ospf_lsa_new(); new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); + new->vrf_id = area->ospf->vrf_id; /* Copy LSA to store. */ new->data = ospf_lsa_data_new(length); @@ -1627,6 +1632,7 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, new->area = NULL; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED); + new->vrf_id = ospf->vrf_id; /* Copy LSA data to store, discard stream. */ new->data = ospf_lsa_data_new(length); @@ -2121,14 +2127,15 @@ int ospf_default_originate_timer(struct thread *thread) void ospf_nssa_lsa_flush(struct ospf *ospf, struct prefix_ipv4 *p) { struct listnode *node, *nnode; - struct ospf_lsa *lsa; + struct ospf_lsa *lsa = NULL; struct ospf_area *area; for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) { if (area->external_routing == OSPF_AREA_NSSA) { - if (!(lsa = ospf_lsa_lookup(area, OSPF_AS_NSSA_LSA, - p->prefix, - ospf->router_id))) { + lsa = ospf_lsa_lookup(ospf, area, + OSPF_AS_NSSA_LSA, p->prefix, + ospf->router_id); + if (!lsa) { if (IS_DEBUG_OSPF(lsa, LSA_FLOODING)) zlog_debug( "LSA: There is no such AS-NSSA-LSA %s/%d in LSDB", @@ -3046,11 +3053,12 @@ struct ospf_lsa *ospf_lsa_lookup_by_prefix(struct ospf_lsdb *lsdb, u_char type, return lsa; } -struct ospf_lsa *ospf_lsa_lookup(struct ospf_area *area, u_int32_t type, - struct in_addr id, struct in_addr adv_router) +struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *area, + u_int32_t type, struct in_addr id, + struct in_addr adv_router) { - struct ospf *ospf = ospf_lookup(); - assert(ospf); + if (!ospf) + return NULL; switch (type) { case OSPF_ROUTER_LSA: @@ -3120,7 +3128,8 @@ struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area, * they two were forming a unique LSA-ID. */ - match = ospf_lsa_lookup(area, lsah->type, lsah->id, lsah->adv_router); + match = ospf_lsa_lookup(area->ospf, area, lsah->type, lsah->id, + lsah->adv_router); if (match == NULL) if (IS_DEBUG_OSPF(lsa, LSA) == OSPF_DEBUG_LSA) @@ -3536,7 +3545,7 @@ struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) */ if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) break; - ei = ospf_external_info_check(lsa); + ei = ospf_external_info_check(ospf, lsa); if (ei) new = ospf_external_lsa_refresh(ospf, lsa, ei, LSA_REFRESH_FORCE); diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index ab8e62b6e4..94a34d4a90 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -111,6 +111,9 @@ struct ospf_lsa { /* For Type-9 Opaque-LSAs */ struct ospf_interface *oi; + + /* VRF Id */ + vrf_id_t vrf_id; }; /* OSPF LSA Link Type. */ @@ -267,8 +270,9 @@ extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *, struct external_info *); extern int ospf_external_lsa_originate_timer(struct thread *); extern int ospf_default_originate_timer(struct thread *); -extern struct ospf_lsa *ospf_lsa_lookup(struct ospf_area *, u_int32_t, - struct in_addr, struct in_addr); +extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *, + u_int32_t, struct in_addr, + struct in_addr); extern struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *, u_int32_t, struct in_addr); extern struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *, diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index f284a04cbe..7bd644f43d 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -187,7 +187,7 @@ int main(int argc, char **argv) /* Library inits. */ debug_init(); - vrf_init(NULL, NULL, NULL, NULL); + ospf_vrf_init(); access_list_init(); prefix_list_init(); diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index c72c69856c..d1c1429054 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -153,7 +153,10 @@ int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex) if (ret < 0) zlog_warn("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", top->fd, safe_strerror(errno)); - +#ifndef GNU_LINUX + /* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send + * packet out of ifindex. Below would be used Non Linux system. + */ ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); if (ret < 0) zlog_warn( @@ -161,23 +164,53 @@ int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex) "ifindex %u): %s", top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno)); +#endif return ret; } -int ospf_sock_init(void) +int ospf_bind_vrfdevice(struct ospf *ospf, int ospf_sock) +{ + int ret = 0; + +#ifdef SO_BINDTODEVICE + + if (ospf && ospf->vrf_id != VRF_DEFAULT && + ospf->vrf_id != VRF_UNKNOWN) { + ret = setsockopt(ospf_sock, SOL_SOCKET, SO_BINDTODEVICE, + ospf->name, + strlen(ospf->name)); + if (ret < 0) { + int save_errno = errno; + + zlog_warn("%s: Could not setsockopt SO_BINDTODEVICE %s", + __PRETTY_FUNCTION__, + safe_strerror(save_errno)); + } else { + zlog_debug("%s: Bind socket %d to vrf %s id %u device", + __PRETTY_FUNCTION__, ospf_sock, + ospf->name, ospf->vrf_id); + } + } +#endif + return ret; +} + +int ospf_sock_init(struct ospf *ospf) { int ospf_sock; int ret, hincl = 1; int bufsize = (8 * 1024 * 1024); - if (ospfd_privs.change(ZPRIVS_RAISE)) + if (ospfd_privs.change(ZPRIVS_RAISE)) { zlog_err("ospf_sock_init: could not raise privs, %s", safe_strerror(errno)); + } ospf_sock = socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP); if (ospf_sock < 0) { int save_errno = errno; + if (ospfd_privs.change(ZPRIVS_LOWER)) zlog_err("ospf_sock_init: could not lower privs, %s", safe_strerror(errno)); @@ -186,17 +219,20 @@ int ospf_sock_init(void) exit(1); } + ret = ospf_bind_vrfdevice(ospf, ospf_sock); + if (ret < 0) + goto out; + #ifdef IP_HDRINCL /* we will include IP header with packet */ ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)); if (ret < 0) { int save_errno = errno; - if (ospfd_privs.change(ZPRIVS_LOWER)) - zlog_err("ospf_sock_init: could not lower privs, %s", - safe_strerror(errno)); + zlog_warn("Can't set IP_HDRINCL option for fd %d: %s", ospf_sock, safe_strerror(save_errno)); + goto out; } #elif defined(IPTOS_PREC_INTERNETCONTROL) #warning "IP_HDRINCL not available on this system" @@ -204,13 +240,11 @@ int ospf_sock_init(void) ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL); if (ret < 0) { int save_errno = errno; - if (ospfd_privs.change(ZPRIVS_LOWER)) - zlog_err("ospf_sock_init: could not lower privs, %s", - safe_strerror(errno)); + zlog_warn("can't set sockopt IP_TOS %d to socket %d: %s", tos, ospf_sock, safe_strerror(save_errno)); close(ospf_sock); /* Prevent sd leak. */ - return ret; + goto out; } #else /* !IPTOS_PREC_INTERNETCONTROL */ #warning "IP_HDRINCL not available, nor is IPTOS_PREC_INTERNETCONTROL" @@ -222,13 +256,14 @@ int ospf_sock_init(void) if (ret < 0) zlog_warn("Can't set pktinfo option for fd %d", ospf_sock); + setsockopt_so_sendbuf(ospf_sock, bufsize); + setsockopt_so_recvbuf(ospf_sock, bufsize); + + ospf->fd = ospf_sock; +out: if (ospfd_privs.change(ZPRIVS_LOWER)) { zlog_err("ospf_sock_init: could not lower privs, %s", safe_strerror(errno)); } - - setsockopt_so_sendbuf(ospf_sock, bufsize); - setsockopt_so_recvbuf(ospf_sock, bufsize); - - return ospf_sock; + return ret; } diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index ed5e00315c..41a7abda70 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -29,6 +29,7 @@ extern int ospf_if_drop_allspfrouters(struct ospf *, struct prefix *, extern int ospf_if_add_alldrouters(struct ospf *, struct prefix *, ifindex_t); extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t); extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t); -extern int ospf_sock_init(void); +extern int ospf_sock_init(struct ospf *ospf); +extern int ospf_bind_vrfdevice(struct ospf *, int); #endif /* _ZEBRA_OSPF_NETWORK_H */ diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index db523bd2a4..bc71e371b1 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -544,7 +544,7 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab, listnode_add(new->area->opaque_lsa_self, oipt); break; case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(new->vrf_id); if (new->area != NULL && (top = new->area->ospf) == NULL) { free_opaque_info_per_type((void *)oipt); oipt = NULL; @@ -648,7 +648,7 @@ lookup_opaque_info_by_type(struct ospf_lsa *lsa) "Type-10 Opaque-LSA: Reference to AREA is missing?"); break; case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(lsa->vrf_id); if ((area = lsa->area) != NULL && (top = area->ospf) == NULL) { zlog_warn( "Type-11 Opaque-LSA: Reference to OSPF is missing?"); @@ -1571,7 +1571,7 @@ struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc) } break; case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(lsa->vrf_id); if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) { /* Above conditions must have passed. */ zlog_warn("ospf_opaque_lsa_install: Sonmething wrong?"); @@ -1597,7 +1597,7 @@ struct ospf_lsa *ospf_opaque_lsa_refresh(struct ospf_lsa *lsa) struct ospf_opaque_functab *functab; struct ospf_lsa *new = NULL; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(lsa->vrf_id); if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL || functab->lsa_refresher == NULL) { @@ -1638,7 +1638,7 @@ static int ospf_opaque_lsa_refresh_timer(struct thread *t); void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent, u_char lsa_type, u_char opaque_type) { - struct ospf *top; + struct ospf *top = NULL; struct ospf_area dummy, *area = NULL; struct ospf_interface *oi = NULL; @@ -1739,6 +1739,7 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent, /* Generate a dummy lsa to be passed for a lookup function. */ lsa = pseudo_lsa(oi, area, lsa_type, opaque_type); + lsa->vrf_id = top->vrf_id; if ((oipt = lookup_opaque_info_by_type(lsa)) == NULL) { struct ospf_opaque_functab *functab; @@ -1804,6 +1805,7 @@ static struct ospf_lsa *pseudo_lsa(struct ospf_interface *oi, lsa.oi = oi; lsa.area = area; lsa.data = &lsah; + lsa.vrf_id = VRF_DEFAULT; lsah.type = lsa_type; tmp = SET_OPAQUE_LSID(opaque_type, 0); /* Opaque-ID is unused here. */ @@ -2000,7 +2002,7 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0) ospf_ls_retransmit_delete_nbr_area(lsa->area, lsa); break; case OSPF_OPAQUE_AS_LSA: - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(lsa0->vrf_id); if ((lsa0->area != NULL) && (lsa0->area->ospf != NULL)) top = lsa0->area->ospf; ospf_ls_retransmit_delete_nbr_as(top, lsa); @@ -2054,7 +2056,7 @@ void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0) struct ospf_lsa *lsa; struct ospf *top; - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(lsa0->vrf_id); if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL || (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) { diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 0ab83c407f..015eac096c 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -649,6 +649,12 @@ static int ospf_write(struct thread *thread) #define OSPF_WRITE_IPHL_SHIFT 2 int pkt_count = 0; +#ifdef GNU_LINUX + unsigned char cmsgbuf[64] = {}; + struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf; + struct in_pktinfo *pi; +#endif + ospf->t_write = NULL; node = listhead(ospf->oi_write_q); @@ -753,14 +759,28 @@ static int ospf_write(struct thread *thread) msg.msg_namelen = sizeof(sa_dst); msg.msg_iov = iov; msg.msg_iovlen = 2; + iov[0].iov_base = (char *)&iph; iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT; iov[1].iov_base = STREAM_PNT(op->s); iov[1].iov_len = op->length; -/* Sadly we can not rely on kernels to fragment packets because of either - * IP_HDRINCL and/or multicast destination being set. - */ +#ifdef GNU_LINUX + msg.msg_control = (caddr_t)cm; + cm->cmsg_level = SOL_IP; + cm->cmsg_type = IP_PKTINFO; + cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + pi = (struct in_pktinfo *)CMSG_DATA(cm); + pi->ipi_ifindex = oi->ifp->ifindex; + + msg.msg_controllen = cm->cmsg_len; +#endif + + /* Sadly we can not rely on kernels to fragment packets + * because of either IP_HDRINCL and/or multicast + * destination being set. + */ + #ifdef WANT_OSPF_WRITE_FRAGMENT if (op->length > maxdatasize) ospf_write_frags(ospf->fd, op, &iph, &msg, maxdatasize, @@ -907,9 +927,10 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh, } if (IS_DEBUG_OSPF_EVENT) - zlog_debug("Packet %s [Hello:RECV]: Options %s", + zlog_debug("Packet %s [Hello:RECV]: Options %s vrf %s", inet_ntoa(ospfh->router_id), - ospf_options_dump(hello->options)); + ospf_options_dump(hello->options), + ospf_vrf_id_to_name(oi->ospf->vrf_id)); /* Compare options. */ #define REJECT_IF_TBIT_ON 1 /* XXX */ @@ -1556,7 +1577,8 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh, } /* Search proper LSA in LSDB. */ - find = ospf_lsa_lookup(oi->area, ls_type, ls_id, adv_router); + find = ospf_lsa_lookup(oi->ospf, oi->area, ls_type, ls_id, + adv_router); if (find == NULL) { OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq); list_delete(ls_upd); @@ -1696,6 +1718,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr, /* Create OSPF LSA instance. */ lsa = ospf_lsa_new(); + lsa->vrf_id = oi->ospf->vrf_id; /* We may wish to put some error checking if type NSSA comes in and area not in NSSA mode */ switch (lsah->type) { @@ -1784,6 +1807,8 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph, */ lsas = ospf_ls_upd_list_lsa(nbr, s, oi, size); + if (lsas == NULL) + return; #define DISCARD_LSA(L, N) \ { \ if (IS_DEBUG_OSPF_EVENT) \ @@ -2173,6 +2198,7 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, lsa = ospf_lsa_new(); lsa->data = (struct lsa_header *)STREAM_PNT(s); + lsa->vrf_id = oi->ospf->vrf_id; /* lsah = (struct lsa_header *) STREAM_PNT (s); */ size -= OSPF_LSA_HEADER_SIZE; @@ -2197,7 +2223,8 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh, return; } -static struct stream *ospf_recv_packet(int fd, struct interface **ifp, +static struct stream *ospf_recv_packet(struct ospf *ospf, int fd, + struct interface **ifp, struct stream *ibuf) { int ret; @@ -2265,7 +2292,7 @@ static struct stream *ospf_recv_packet(int fd, struct interface **ifp, ifindex = getsockopt_ifindex(AF_INET, &msgh); - *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + *ifp = if_lookup_by_index(ifindex, ospf->vrf_id); if (ret != ip_len) { zlog_warn( @@ -2833,7 +2860,7 @@ int ospf_read(struct thread *thread) struct ip *iph; struct ospf_header *ospfh; u_int16_t length; - struct interface *ifp; + struct interface *ifp = NULL; struct connected *c; /* first of all get interface pointer. */ @@ -2844,7 +2871,8 @@ int ospf_read(struct thread *thread) thread_add_read(master, ospf_read, ospf, ospf->fd, &ospf->t_read); stream_reset(ospf->ibuf); - if (!(ibuf = ospf_recv_packet(ospf->fd, &ifp, ospf->ibuf))) + ibuf = ospf_recv_packet(ospf, ospf->fd, &ifp, ospf->ibuf); + if (ibuf == NULL) return -1; /* This raw packet is known to be at least as big as its IP header. */ @@ -2861,7 +2889,7 @@ int ospf_read(struct thread *thread) ifindex retrieval but do not. */ c = if_lookup_address((void *)&iph->ip_src, AF_INET, - VRF_DEFAULT); + ospf->vrf_id); if (c) ifp = c->ifp; if (ifp == NULL) @@ -3487,6 +3515,13 @@ static void ospf_hello_send_sub(struct ospf_interface *oi, in_addr_t addr) op->dst.s_addr = addr; + if (IS_DEBUG_OSPF_EVENT) { + if (oi->ospf->vrf_id) + zlog_debug("%s: Hello Tx interface %s ospf vrf %s id %u", + __PRETTY_FUNCTION__, oi->ifp->name, + ospf_vrf_id_to_name(oi->ospf->vrf_id), + oi->ospf->vrf_id); + } /* 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 */ diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 13013bf8ca..f9e346b1d1 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -427,7 +427,7 @@ static void initialize_params(struct ospf_router_info *ori) /* If Area address is not null and exist, retrieve corresponding * structure */ - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(VRF_DEFAULT); zlog_info("RI-> Initialize Router Info for %s scope within area %s", OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", inet_ntoa(OspfRI.area_id)); @@ -586,7 +586,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new() "LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance", lsa_type, inet_ntoa(lsa_id)); - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Set opaque-LSA header fields. */ lsa_header_set(s, options, lsa_type, lsa_id, top->router_id); @@ -615,6 +615,11 @@ static struct ospf_lsa *ospf_router_info_lsa_new() new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */ + if (new->area && new->area->ospf) + new->vrf_id = new->area->ospf->vrf_id; + else + new->vrf_id = VRF_DEFAULT; + SET_FLAG(new->flags, OSPF_LSA_SELF); memcpy(new->data, lsah, length); stream_free(s); @@ -628,6 +633,7 @@ static int ospf_router_info_lsa_originate1(void *arg) struct ospf *top; struct ospf_area *area; int rc = -1; + vrf_id_t vrf_id = VRF_DEFAULT; /* First check if the area is known if flooding scope is Area */ if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA) { @@ -638,6 +644,8 @@ static int ospf_router_info_lsa_originate1(void *arg) return rc; } OspfRI.area = area; + if (area->ospf) + vrf_id = area->ospf->vrf_id; } /* Create new Opaque-LSA/ROUTER INFORMATION instance. */ @@ -646,9 +654,15 @@ static int ospf_router_info_lsa_originate1(void *arg) "ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?"); return rc; } + new->vrf_id = vrf_id; /* Get ospf info */ - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(vrf_id); + if (top == NULL) { + zlog_debug("%s: ospf instance not found for vrf id %u", + __PRETTY_FUNCTION__, vrf_id); + return rc; + } /* Install this LSA into LSDB. */ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { @@ -751,10 +765,11 @@ static struct ospf_lsa *ospf_router_info_lsa_refresh(struct ospf_lsa *lsa) return NULL; } new->data->ls_seqnum = lsa_seqnum_increment(lsa); + new->vrf_id = lsa->vrf_id; /* Install this LSA into LSDB. */ /* Given "lsa" will be freed in the next function. */ - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(lsa->vrf_id); if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { zlog_warn("ospf_router_info_lsa_refresh: ospf_lsa_install() ?"); ospf_lsa_unlock(&new); @@ -800,7 +815,7 @@ static void ospf_router_info_lsa_schedule(enum lsa_opcode opcode) if (CHECK_FLAG(OspfRI.flags, RIFLG_LSA_ENGAGED) && (opcode == REORIGINATE_THIS_LSA)) opcode = REFRESH_THIS_LSA; - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(VRF_DEFAULT); if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL)) { zlog_warn( "ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set"); diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 89ea331b52..ca851ec75d 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -83,7 +83,7 @@ void ospf_path_free(struct ospf_path *op) XFREE(MTYPE_OSPF_PATH, op); } -void ospf_route_delete(struct route_table *rt) +void ospf_route_delete(struct ospf *ospf, struct route_table *rt) { struct route_node *rn; struct ospf_route * or ; @@ -91,10 +91,11 @@ void ospf_route_delete(struct route_table *rt) for (rn = route_top(rt); rn; rn = route_next(rn)) if ((or = rn->info) != NULL) { if (or->type == OSPF_DESTINATION_NETWORK) - ospf_zebra_delete((struct prefix_ipv4 *)&rn->p, + ospf_zebra_delete(ospf, + (struct prefix_ipv4 *)&rn->p, or); else if (or->type == OSPF_DESTINATION_DISCARD) - ospf_zebra_delete_discard( + ospf_zebra_delete_discard(ospf, (struct prefix_ipv4 *)&rn->p); } } @@ -191,7 +192,8 @@ int ospf_route_match_same(struct route_table *rt, struct prefix_ipv4 *prefix, /* delete routes generated from AS-External routes if there is a inter/intra * area route */ -static void ospf_route_delete_same_ext(struct route_table *external_routes, +static void ospf_route_delete_same_ext(struct ospf *ospf, + struct route_table *external_routes, struct route_table *routes) { struct route_node *rn, *ext_rn; @@ -206,7 +208,8 @@ static void ospf_route_delete_same_ext(struct route_table *external_routes, if ((ext_rn = route_node_lookup(external_routes, (struct prefix *)p))) { if (ext_rn->info) { - ospf_zebra_delete(p, ext_rn->info); + ospf_zebra_delete(ospf, p, + ext_rn->info); ospf_route_free(ext_rn->info); ext_rn->info = NULL; } @@ -217,7 +220,7 @@ static void ospf_route_delete_same_ext(struct route_table *external_routes, } /* rt: Old, cmprt: New */ -static void ospf_route_delete_uniq(struct route_table *rt, +static void ospf_route_delete_uniq(struct ospf *ospf, struct route_table *rt, struct route_table *cmprt) { struct route_node *rn; @@ -232,7 +235,7 @@ static void ospf_route_delete_uniq(struct route_table *rt, cmprt, (struct prefix_ipv4 *)&rn ->p)) - ospf_zebra_delete( + ospf_zebra_delete(ospf, (struct prefix_ipv4 *)&rn->p, or); @@ -241,7 +244,7 @@ static void ospf_route_delete_uniq(struct route_table *rt, cmprt, (struct prefix_ipv4 *)&rn ->p)) - ospf_zebra_delete_discard( + ospf_zebra_delete_discard(ospf, (struct prefix_ipv4 *)&rn->p); } @@ -263,9 +266,9 @@ void ospf_route_install(struct ospf *ospf, struct route_table *rt) /* Delete old routes. */ if (ospf->old_table) - ospf_route_delete_uniq(ospf->old_table, rt); + ospf_route_delete_uniq(ospf, ospf->old_table, rt); if (ospf->old_external_route) - ospf_route_delete_same_ext(ospf->old_external_route, rt); + ospf_route_delete_same_ext(ospf, ospf->old_external_route, rt); /* Install new routes. */ for (rn = route_top(rt); rn; rn = route_next(rn)) @@ -274,14 +277,14 @@ void ospf_route_install(struct ospf *ospf, struct route_table *rt) if (!ospf_route_match_same( ospf->old_table, (struct prefix_ipv4 *)&rn->p, or)) - ospf_zebra_add( + ospf_zebra_add(ospf, (struct prefix_ipv4 *)&rn->p, or); } else if (or->type == OSPF_DESTINATION_DISCARD) if (!ospf_route_match_same( ospf->old_table, (struct prefix_ipv4 *)&rn->p, or)) - ospf_zebra_add_discard( + ospf_zebra_add_discard(ospf, (struct prefix_ipv4 *)&rn->p); } } @@ -906,7 +909,8 @@ void ospf_prune_unreachable_routers(struct route_table *rtrs) } } -int ospf_add_discard_route(struct route_table *rt, struct ospf_area *area, +int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt, + struct ospf_area *area, struct prefix_ipv4 *p) { struct route_node *rn; @@ -961,12 +965,13 @@ int ospf_add_discard_route(struct route_table *rt, struct ospf_area *area, new_or->path_type = OSPF_PATH_INTER_AREA; rn->info = new_or; - ospf_zebra_add_discard(p); + ospf_zebra_add_discard(ospf, p); return 1; } -void ospf_delete_discard_route(struct route_table *rt, struct prefix_ipv4 *p) +void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt, + struct prefix_ipv4 *p) { struct route_node *rn; struct ospf_route * or ; @@ -1012,7 +1017,7 @@ void ospf_delete_discard_route(struct route_table *rt, struct prefix_ipv4 *p) route_unlock_node(rn); /* remove the discard entry from the rib */ - ospf_zebra_delete_discard(p); + ospf_zebra_delete_discard(ospf, p); return; } diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 1999379844..76df54fb3f 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -115,7 +115,7 @@ extern void ospf_path_free(struct ospf_path *); extern struct ospf_path *ospf_path_lookup(struct list *, struct ospf_path *); extern struct ospf_route *ospf_route_new(void); extern void ospf_route_free(struct ospf_route *); -extern void ospf_route_delete(struct route_table *); +extern void ospf_route_delete(struct ospf *, struct route_table *); extern void ospf_route_table_free(struct route_table *); extern void ospf_route_install(struct ospf *, struct route_table *); @@ -145,9 +145,9 @@ extern void ospf_route_add(struct route_table *, struct prefix_ipv4 *, extern void ospf_route_subst_nexthops(struct ospf_route *, struct list *); extern void ospf_prune_unreachable_networks(struct route_table *); extern void ospf_prune_unreachable_routers(struct route_table *); -extern int ospf_add_discard_route(struct route_table *, struct ospf_area *, - struct prefix_ipv4 *); -extern void ospf_delete_discard_route(struct route_table *, +extern int ospf_add_discard_route(struct ospf *, struct route_table *, + struct ospf_area *, struct prefix_ipv4 *); +extern void ospf_delete_discard_route(struct ospf *, struct route_table *, struct prefix_ipv4 *); extern int ospf_route_match_same(struct route_table *, struct prefix_ipv4 *, struct ospf_route *); diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index f47e2b6f1e..b7a47602d0 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -45,38 +45,40 @@ static void ospf_route_map_update(const char *name) { struct ospf *ospf; int type; + struct listnode *n1 = NULL; /* If OSPF instatnce does not exist, return right now. */ - ospf = ospf_lookup(); - if (ospf == NULL) + if (listcount(om->ospf) == 0) return; - /* Update route-map */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { + /* Update route-map */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; - red_list = ospf->redist[type]; - if (!red_list) - continue; + red_list = ospf->redist[type]; + if (!red_list) + continue; - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { - if (ROUTEMAP_NAME(red) - && strcmp(ROUTEMAP_NAME(red), name) == 0) { - /* Keep old route-map. */ - struct route_map *old = ROUTEMAP(red); + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP_NAME(red) + && strcmp(ROUTEMAP_NAME(red), name) == 0) { + /* Keep old route-map. */ + struct route_map *old = ROUTEMAP(red); - /* Update route-map. */ - ROUTEMAP(red) = route_map_lookup_by_name( - ROUTEMAP_NAME(red)); + /* Update route-map. */ + ROUTEMAP(red) = route_map_lookup_by_name( + ROUTEMAP_NAME(red)); - /* No update for this distribute type. */ - if (old == NULL && ROUTEMAP(red) == NULL) - continue; + /* No update for this distribute type. */ + if (old == NULL && ROUTEMAP(red) == NULL) + continue; - ospf_distribute_list_update(ospf, type, - red->instance); + ospf_distribute_list_update(ospf, type, + red->instance); + } } } } @@ -86,26 +88,24 @@ static void ospf_route_map_event(route_map_event_t event, const char *name) { struct ospf *ospf; int type; + struct listnode *n1 = NULL; - /* If OSPF instatnce does not exist, return right now. */ - ospf = ospf_lookup(); - if (ospf == NULL) - return; + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; + red_list = ospf->redist[type]; + if (!red_list) + continue; - red_list = ospf->redist[type]; - if (!red_list) - continue; - - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { - if (ROUTEMAP_NAME(red) && ROUTEMAP(red) - && !strcmp(ROUTEMAP_NAME(red), name)) { - ospf_distribute_list_update(ospf, type, - red->instance); + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP_NAME(red) && ROUTEMAP(red) + && !strcmp(ROUTEMAP_NAME(red), name)) { + ospf_distribute_list_update(ospf, type, + red->instance); + } } } } @@ -285,7 +285,7 @@ static route_map_result_t route_match_interface(void *rule, if (type == RMAP_OSPF) { ei = object; - ifp = if_lookup_by_name((char *)rule, VRF_DEFAULT); + ifp = if_lookup_by_name_all_vrf((char *)rule); if (ifp == NULL || ifp->ifindex != ei->ifindex) return RMAP_NOMATCH; diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index 6a352380b8..36ae091f99 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -532,7 +532,7 @@ static u_char *ospfGeneralGroup(struct variable *v, oid *name, size_t *length, { struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Check whether the instance identifier is valid */ if (smux_header_generic(v, name, length, exact, var_len, write_method) @@ -661,7 +661,7 @@ static struct ospf_area *ospfAreaLookup(struct variable *v, oid name[], struct ospf_area *area; int len; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -765,7 +765,7 @@ static struct ospf_area *ospf_stub_area_lookup_next(struct in_addr *area_id, struct listnode *node; struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -792,7 +792,7 @@ static struct ospf_area *ospfStubAreaLookup(struct variable *v, oid name[], struct ospf_area *area; int len; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -934,7 +934,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name, oid *offset; int offsetlen; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); #define OSPF_LSDB_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE) @@ -1084,7 +1084,7 @@ static u_char *ospfLsdbEntry(struct variable *v, oid *name, size_t *length, memset(&router_id, 0, sizeof(struct in_addr)); /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -1145,7 +1145,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v, p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (exact) { /* Area ID + Range Network. */ @@ -1239,7 +1239,7 @@ static u_char *ospfAreaRangeEntry(struct variable *v, oid *name, size_t *length, return NULL; /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -1290,7 +1290,7 @@ static struct ospf_nbr_nbma *ospfHostLookup(struct variable *v, oid *name, struct ospf_nbr_nbma *nbr_nbma; struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -1347,7 +1347,7 @@ static u_char *ospfHostEntry(struct variable *v, oid *name, size_t *length, return NULL; /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -1504,7 +1504,7 @@ static struct ospf_interface *ospf_snmp_if_lookup(struct in_addr *ifaddr, struct listnode *node; struct ospf_snmp_if *osif; struct ospf_interface *oi = NULL; - struct ospf *ospf = ospf_lookup(); + struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); for (ALL_LIST_ELEMENTS_RO(ospf_snmp_iflist, node, osif)) { if (ifaddr->s_addr) { @@ -1527,7 +1527,7 @@ static struct ospf_interface *ospf_snmp_if_lookup_next(struct in_addr *ifaddr, { struct ospf_snmp_if *osif; struct listnode *nn; - struct ospf *ospf = ospf_lookup(); + struct ospf *ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); struct ospf_interface *oi = NULL; if (ospf == NULL) @@ -1675,7 +1675,7 @@ static u_char *ospfIfEntry(struct variable *v, oid *name, size_t *length, memset(&ifaddr, 0, sizeof(struct in_addr)); /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -1845,7 +1845,7 @@ static u_char *ospfIfMetricEntry(struct variable *v, oid *name, size_t *length, memset(&ifaddr, 0, sizeof(struct in_addr)); /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -2125,7 +2125,7 @@ static struct ospf_neighbor *ospf_snmp_nbr_lookup_next(struct in_addr *nbr_addr, struct ospf_neighbor *min = NULL; struct ospf *ospf = ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, nn, oi)) { for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) @@ -2165,7 +2165,7 @@ static struct ospf_neighbor *ospfNbrLookup(struct variable *v, oid *name, struct ospf_neighbor *nbr; struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (!ospf) return NULL; @@ -2325,7 +2325,7 @@ static u_char *ospfVirtNbrEntry(struct variable *v, oid *name, size_t *length, memset(&neighbor, 0, sizeof(struct in_addr)); /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; @@ -2379,7 +2379,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name, struct ospf_lsa *lsa; struct ospf *ospf; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (exact) { if (*length != v->namelen + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE) return NULL; @@ -2476,7 +2476,7 @@ static u_char *ospfExtLsdbEntry(struct variable *v, oid *name, size_t *length, memset(&router_id, 0, sizeof(struct in_addr)); /* Check OSPF instance. */ - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); if (ospf == NULL) return NULL; diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 891088ecc2..5e57426089 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -781,7 +781,8 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area, * of candidates with any vertices not already on the list. If a lower-cost * path is found to a vertex already on the candidate list, store the new cost. */ -static void ospf_spf_next(struct vertex *v, struct ospf_area *area, +static void ospf_spf_next(struct vertex *v, struct ospf *ospf, + struct ospf_area *area, struct pqueue *candidate) { struct ospf_lsa *w_lsa = NULL; @@ -841,7 +842,8 @@ static void ospf_spf_next(struct vertex *v, struct ospf_area *area, inet_ntoa(l->link_id)); } - w_lsa = ospf_lsa_lookup(area, OSPF_ROUTER_LSA, + w_lsa = ospf_lsa_lookup(ospf, area, + OSPF_ROUTER_LSA, l->link_id, l->link_id); if (w_lsa) { if (IS_DEBUG_OSPF_EVENT) @@ -1159,7 +1161,7 @@ ospf_rtrs_print (struct route_table *rtrs) #endif /* Calculating the shortest-path tree for an area. */ -static void ospf_spf_calculate(struct ospf_area *area, +static void ospf_spf_calculate(struct ospf *ospf, struct ospf_area *area, struct route_table *new_table, struct route_table *new_rtrs) { @@ -1209,7 +1211,7 @@ static void ospf_spf_calculate(struct ospf_area *area, for (;;) { /* RFC2328 16.1. (2). */ - ospf_spf_next(v, area, candidate); + ospf_spf_next(v, ospf, area, candidate); /* RFC2328 16.1. (3). */ /* If at this step the candidate list is empty, the shortest- @@ -1307,13 +1309,13 @@ static int ospf_spf_calculate_timer(struct thread *thread) if (ospf->backbone && ospf->backbone == area) continue; - ospf_spf_calculate(area, new_table, new_rtrs); + ospf_spf_calculate(ospf, area, new_table, new_rtrs); areas_processed++; } /* SPF for backbone, if required */ if (ospf->backbone) { - ospf_spf_calculate(ospf->backbone, new_table, new_rtrs); + ospf_spf_calculate(ospf, ospf->backbone, new_table, new_rtrs); areas_processed++; } @@ -1339,6 +1341,12 @@ static int ospf_spf_calculate_timer(struct thread *thread) ospf_ase_calculate_timer_add(ospf); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ospf install new route, vrf %s id %u new_table count %lu", + __PRETTY_FUNCTION__, + ospf_vrf_id_to_name(ospf->vrf_id), + ospf->vrf_id, new_table->count); /* Update routing table. */ monotime(&start_time); ospf_route_install(ospf, new_table); diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 5517008909..294ffe48b3 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -728,7 +728,7 @@ static void update_linkparams(struct mpls_te_link *lp) else { lp->flags = INTER_AS | FLOOD_AREA; lp->area = ospf_area_lookup_by_area_id( - ospf_lookup(), + ospf_lookup_by_vrf_id(VRF_DEFAULT), OspfMplsTE.interas_areaid); } } @@ -1127,7 +1127,8 @@ static void ospf_mpls_te_lsa_body_set(struct stream *s, struct mpls_te_link *lp) } /* Create new opaque-LSA. */ -static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area, +static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf, + struct ospf_area *area, struct mpls_te_link *lp) { struct stream *s; @@ -1167,9 +1168,10 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area, tmp = SET_OPAQUE_LSID(OPAQUE_TYPE_INTER_AS_LSA, lp->instance); lsa_id.s_addr = htonl(tmp); - struct ospf *top = ospf_lookup(); + if (!ospf) + return NULL; - lsa_header_set(s, options, lsa_type, lsa_id, top->router_id); + lsa_header_set(s, options, lsa_type, lsa_id, ospf->router_id); } else { options |= LSA_OPTIONS_GET(area); /* Get area default option */ options |= LSA_OPTIONS_NSSA_GET(area); @@ -1207,6 +1209,9 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area, return new; } + new->vrf_id = ospf->vrf_id; + if (area && area->ospf) + new->vrf_id = area->ospf->vrf_id; new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF); memcpy(new->data, lsah, length); @@ -1218,11 +1223,12 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf_area *area, static int ospf_mpls_te_lsa_originate1(struct ospf_area *area, struct mpls_te_link *lp) { - struct ospf_lsa *new; + struct ospf_lsa *new = NULL; int rc = -1; /* Create new Opaque-LSA/MPLS-TE instance. */ - if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) { + new = ospf_mpls_te_lsa_new(area->ospf, area, lp); + if (new == NULL) { zlog_warn( "ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?"); return rc; @@ -1321,11 +1327,13 @@ static int ospf_mpls_te_lsa_originate2(struct ospf *top, int rc = -1; /* Create new Opaque-LSA/Inter-AS instance. */ - if ((new = ospf_mpls_te_lsa_new(NULL, lp)) == NULL) { + new = ospf_mpls_te_lsa_new(top, NULL, lp); + if (new == NULL) { zlog_warn( "ospf_mpls_te_lsa_originate2: ospf_router_info_lsa_new() ?"); return rc; } + new->vrf_id = top->vrf_id; /* Install this LSA into LSDB. */ if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { @@ -1451,9 +1459,10 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa) ospf_opaque_lsa_flush_schedule(lsa); return NULL; } - + top = ospf_lookup_by_vrf_id(lsa->vrf_id); /* Create new Opaque-LSA/MPLS-TE instance. */ - if ((new = ospf_mpls_te_lsa_new(area, lp)) == NULL) { + new = ospf_mpls_te_lsa_new(top, area, lp); + if (new == NULL) { zlog_warn("ospf_mpls_te_lsa_refresh: ospf_mpls_te_lsa_new() ?"); return NULL; } @@ -1465,8 +1474,6 @@ static struct ospf_lsa *ospf_mpls_te_lsa_refresh(struct ospf_lsa *lsa) * ospf_lookup() to get ospf instance */ if (area) top = area->ospf; - else - top = ospf_lookup(); if (ospf_lsa_install(top, NULL /*oi */, new) == NULL) { zlog_warn("ospf_mpls_te_lsa_refresh: ospf_lsa_install() ?"); @@ -1500,7 +1507,7 @@ void ospf_mpls_te_lsa_schedule(struct mpls_te_link *lp, enum lsa_opcode opcode) memset(&lsa, 0, sizeof(lsa)); memset(&lsah, 0, sizeof(lsah)); - top = ospf_lookup(); + top = ospf_lookup_by_vrf_id(VRF_DEFAULT); /* Check if the pseudo link is ready to flood */ if (!(CHECK_FLAG(lp->flags, LPFLG_LSA_ACTIVE)) @@ -2517,29 +2524,64 @@ static void show_mpls_te_link_sub(struct vty *vty, struct interface *ifp) DEFUN (show_ip_ospf_mpls_te_link, show_ip_ospf_mpls_te_link_cmd, - "show ip ospf mpls-te interface [INTERFACE]", + "show ip ospf [vrf ] mpls-te interface [INTERFACE]", SHOW_STR IP_STR OSPF_STR + VRF_CMD_HELP_STR + "All VRFs\n" "MPLS-TE information\n" "Interface information\n" "Interface name\n") { int idx_interface = 5; struct interface *ifp; - struct listnode *node, *nnode; + struct listnode *node, *nnode, *n1; + char *vrf_name = NULL; + bool all_vrf; + int inst = 0; + int idx_vrf = 0; + struct ospf *ospf = NULL; + if (argv_find(argv, argc, "vrf", &idx_vrf)) { + vrf_name = argv[idx_vrf + 1]->arg; + all_vrf = strmatch(vrf_name, "all"); + } + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { + if (!ospf->oi_running) + continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(ospf->vrf_id), + node, nnode, ifp)) + show_mpls_te_link_sub(vty, ifp); + } + return CMD_SUCCESS; + } + ospf = ospf_lookup_by_inst_name (inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + for (ALL_LIST_ELEMENTS(vrf_iflist(ospf->vrf_id), node, + nnode, ifp)) + show_mpls_te_link_sub(vty, ifp); + return CMD_SUCCESS; + } /* Show All Interfaces. */ if (argc == 5) { - for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, - ifp)) - show_mpls_te_link_sub(vty, ifp); + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { + if (!ospf->oi_running) + continue; + for (ALL_LIST_ELEMENTS(vrf_iflist(ospf->vrf_id), node, + nnode, ifp)) + show_mpls_te_link_sub(vty, ifp); + } } /* Interface name is specified. */ else { - if ((ifp = if_lookup_by_name(argv[idx_interface]->arg, - VRF_DEFAULT)) - == NULL) + ifp = if_lookup_by_name_all_vrf(argv[idx_interface]->arg); + if (ifp == NULL) vty_out(vty, "No such interface name\n"); else show_mpls_te_link_sub(vty, ifp); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index cf5fa80f94..3840bc4170 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -126,25 +126,70 @@ int ospf_oi_count(struct interface *ifp) return i; } -DEFUN_NOSH (router_ospf, - router_ospf_cmd, - "router ospf [(1-65535)]", - "Enable a routing process\n" - "Start OSPF configuration\n" - "Instance ID\n") -{ - struct ospf *ospf; - u_short instance = 0; - int ret = CMD_SUCCESS; - - ospf = ospf_lookup(); - if (!ospf) { - vty_out(vty, "There isn't active ospf instance \n"); - return CMD_WARNING_CONFIG_FAILED; +#define OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf) \ + if (argv_find(argv, argc, "vrf", &idx_vrf)) { \ + vrf_name = argv[idx_vrf + 1]->arg; \ + all_vrf = strmatch(vrf_name, "all"); \ } - if (argc > 2) - instance = strtoul(argv[2]->arg, NULL, 10); +static struct ospf *ospf_cmd_lookup_ospf(struct vty *vty, + struct cmd_token *argv[], + const int argc, + uint32_t enable, + u_short *instance) +{ + struct ospf *ospf = NULL; + int idx_vrf = 0; + const char *vrf_name = NULL; + + if (argv_find(argv, argc, "vrf", &idx_vrf)) { + vrf_name = argv[idx_vrf + 1]->arg; + if (enable) { + if (argc > 4) + *instance = strtoul(argv[2]->arg, NULL, 10); + /* Allocate VRF aware instance */ + ospf = ospf_get(*instance, vrf_name); + } else { + if (argc > 5) + *instance = strtoul(argv[3]->arg, NULL, 10); + ospf = ospf_lookup_by_inst_name(*instance, vrf_name); + } + } else { + if (enable) { + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (!ospf) + vty_out(vty, + "There isn't active ospf instance\n"); + if (argc > 2) + *instance = strtoul(argv[2]->arg, NULL, 10); + } else { + if (argc > 3) + *instance = strtoul(argv[3]->arg, NULL, 10); + ospf = ospf_lookup_instance(*instance); + } + } + return ospf; +} + +#ifndef VTYSH_EXTRACT_PL +#include "ospf_vty_clippy.c" +#endif + +DEFUN_NOSH (router_ospf, + router_ospf_cmd, + "router ospf [{(1-65535)|vrf NAME}]", + "Enable a routing process\n" + "Start OSPF configuration\n" + "Instance ID\n" + VRF_CMD_HELP_STR) +{ + struct ospf *ospf = NULL; + int ret = CMD_SUCCESS; + u_short instance = 0; + + ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 1, &instance); + if (!ospf) + return CMD_WARNING_CONFIG_FAILED; /* The following logic to set the vty qobj index is in place to be able to ignore the commands which dont belong to this instance. */ @@ -152,10 +197,12 @@ DEFUN_NOSH (router_ospf, VTY_PUSH_CONTEXT_NULL(OSPF_NODE); ret = CMD_NOT_MY_INSTANCE; } else { + if (ospf->vrf_id != VRF_UNKNOWN) + ospf->oi_running = 1; if (IS_DEBUG_OSPF_EVENT) - zlog_debug("Config command 'router ospf %d' received", - instance); - ospf->oi_running = 1; + zlog_debug("Config command 'router ospf %d' received, vrf %s id %d oi_running %u", + instance, ospf->name ? ospf->name : "NIL", + ospf->vrf_id, ospf->oi_running); VTY_PUSH_CONTEXT(OSPF_NODE, ospf); ospf_router_id_update(ospf); } @@ -165,29 +212,30 @@ DEFUN_NOSH (router_ospf, DEFUN (no_router_ospf, no_router_ospf_cmd, - "no router ospf [(1-65535)]", + "no router ospf [{(1-65535)|vrf NAME}]", NO_STR "Enable a routing process\n" "Start OSPF configuration\n" - "Instance ID\n") + "Instance ID\n" + VRF_CMD_HELP_STR) { struct ospf *ospf; u_short instance = 0; - if (argc > 3) - instance = strtoul(argv[3]->arg, NULL, 10); - - ospf = ospf_lookup_instance(instance); - if (ospf == NULL) - return CMD_NOT_MY_INSTANCE; - + ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 0, &instance); + if (ospf == NULL) { + if (instance) + return CMD_NOT_MY_INSTANCE; + else + return CMD_WARNING; + } ospf_finish(ospf); return CMD_SUCCESS; } -DEFUN (ospf_router_id, +DEFPY (ospf_router_id, ospf_router_id_cmd, "ospf router-id A.B.C.D", "OSPF specific commands\n" @@ -195,17 +243,9 @@ DEFUN (ospf_router_id, "OSPF router-id in IP address format\n") { VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); - int idx_ipv4 = 2; + struct listnode *node; struct ospf_area *area; - struct in_addr router_id; - int ret; - - ret = inet_aton(argv[idx_ipv4]->arg, &router_id); - if (!ret) { - vty_out(vty, "Please specify Router ID by A.B.C.D\n"); - return CMD_WARNING_CONFIG_FAILED; - } ospf->router_id_static = router_id; @@ -256,7 +296,7 @@ DEFUN_HIDDEN (ospf_router_id_old, return CMD_SUCCESS; } -DEFUN (no_ospf_router_id, +DEFPY (no_ospf_router_id, no_ospf_router_id_cmd, "no ospf router-id [A.B.C.D]", NO_STR @@ -268,6 +308,13 @@ DEFUN (no_ospf_router_id, struct listnode *node; struct ospf_area *area; + if (router_id_str) { + if (!IPV4_ADDR_SAME(&ospf->router_id_static, &router_id)) { + vty_out(vty, "%% OSPF router-id doesn't match\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + ospf->router_id_static.s_addr = 0; for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) @@ -292,7 +339,7 @@ static void ospf_passive_interface_default(struct ospf *ospf, u_char newval) ospf->passive_interface_default = newval; - for (ALL_LIST_ELEMENTS_RO(om->iflist, ln, ifp)) { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), ln, ifp)) { if (ifp && OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), passive_interface)) UNSET_IF_PARAM(IF_DEF_PARAMS(ifp), passive_interface); @@ -366,7 +413,12 @@ DEFUN (ospf_passive_interface, return CMD_SUCCESS; } - ifp = if_get_by_name(argv[1]->arg, VRF_DEFAULT); + ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id); + if (ifp == NULL) { + vty_out(vty, "interface %s not found.\n", + (char *)argv[1]->arg); + return CMD_WARNING; + } params = IF_DEF_PARAMS(ifp); @@ -433,7 +485,12 @@ DEFUN (no_ospf_passive_interface, return CMD_SUCCESS; } - ifp = if_get_by_name(argv[2]->arg, VRF_DEFAULT); + ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id); + if (ifp == NULL) { + vty_out(vty, "interface %s not found.\n", + (char *)argv[1]->arg); + return CMD_WARNING; + } params = IF_DEF_PARAMS(ifp); @@ -2416,7 +2473,7 @@ DEFUN (ospf_auto_cost_reference_bandwidth, return CMD_SUCCESS; ospf->ref_bandwidth = refbw; - for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), node, ifp)) ospf_if_recalculate_output_cost(ifp); return CMD_SUCCESS; @@ -2442,7 +2499,7 @@ DEFUN (no_ospf_auto_cost_reference_bandwidth, vty_out(vty, " Please ensure reference bandwidth is consistent across all routers\n"); - for (ALL_LIST_ELEMENTS(om->iflist, node, nnode, ifp)) + for (ALL_LIST_ELEMENTS(vrf_iflist(ospf->vrf_id), node, nnode, ifp)) ospf_if_recalculate_output_cost(ifp); return CMD_SUCCESS; @@ -3102,19 +3159,52 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, DEFUN (show_ip_ospf, show_ip_ospf_cmd, - "show ip ospf [json]", + "show ip ospf [vrf ] [json]", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" JSON_STR) { struct ospf *ospf; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) + if (listcount(om->ospf) == 0) return CMD_SUCCESS; - return (show_ip_ospf_common(vty, ospf, uj)); + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_common(vty, ospf, uj); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if ((ospf == NULL) || !ospf->oi_running) + return CMD_SUCCESS; + } else { + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + /* Display default ospf (instance 0) info */ + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } + + if (ospf) + show_ip_ospf_common(vty, ospf, uj); + + return ret; } DEFUN (show_ip_ospf_instance, @@ -3483,7 +3573,8 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, if (argc == iface_argv) { /* Show All Interfaces.*/ - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), + node, ifp)) { if (ospf_oi_count(ifp)) { if (use_json) json_interface_sub = @@ -3502,7 +3593,7 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, } else { /* Interface name is specified. */ if ((ifp = if_lookup_by_name(argv[iface_argv]->arg, - VRF_DEFAULT)) + ospf->vrf_id)) == NULL) { if (use_json) json_object_boolean_true_add(json, @@ -3534,24 +3625,59 @@ static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, DEFUN (show_ip_ospf_interface, show_ip_ospf_interface_cmd, - "show ip ospf interface [INTERFACE] [json]", + "show ip ospf [vrf ] interface [INTERFACE] [json]", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Interface information\n" "Interface name\n" JSON_STR) { struct ospf *ospf; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); if (uj) argc--; - return show_ip_ospf_interface_common(vty, ospf, argc, argv, 4, uj); + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_interface_common(vty, + ospf, argc, + argv, 6, + uj); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_interface_common(vty, ospf, + argc, argv, 6, uj); + + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_interface_common(vty, ospf, + argc, argv, 4, uj); + } + + return ret; } DEFUN (show_ip_ospf_instance_interface, @@ -3722,8 +3848,6 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, if (use_json) json = json_object_new_object(); - else - show_ip_ospf_neighbour_header(vty); if (ospf->instance) { if (use_json) @@ -3748,20 +3872,54 @@ static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, DEFUN (show_ip_ospf_neighbor, show_ip_ospf_neighbor_cmd, - "show ip ospf neighbor [json]", + "show ip ospf [vrf ] neighbor [json]", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Neighbor list\n" JSON_STR) { struct ospf *ospf; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return show_ip_ospf_neighbor_common(vty, ospf, uj); + if (!uj) + show_ip_ospf_neighbour_header(vty); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_common(vty, ospf, + uj); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } + + if (ospf) + ret = show_ip_ospf_neighbor_common(vty, ospf, uj); + + return ret; } @@ -3788,6 +3946,9 @@ DEFUN (show_ip_ospf_instance_neighbor, if (!ospf->oi_running) return CMD_SUCCESS; + if (!uj) + show_ip_ospf_neighbour_header(vty); + return show_ip_ospf_neighbor_common(vty, ospf, uj); } @@ -3802,8 +3963,7 @@ static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, if (use_json) { json = json_object_new_object(); json_neighbor_sub = json_object_new_object(); - } else - show_ip_ospf_neighbour_header(vty); + } if (ospf->instance) { if (use_json) @@ -3813,6 +3973,22 @@ static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); } + if (ospf->name) { + if (use_json) { + json_object_int_add(json, "vrfId", + (ospf->vrf_id == VRF_UNKNOWN) + ? -1 : ospf->vrf_id); + json_object_string_add(json, "vrfName", + (ospf->vrf_id == VRF_DEFAULT) + ? "Default" : ospf->name); + } else { + vty_out(vty, "\nOSPF vrf: %s\n\n", + ospf->vrf_id == VRF_DEFAULT + ? "Default" : ospf->name); + } + } + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { struct listnode *nbr_node; struct ospf_nbr_nbma *nbr_nbma; @@ -3871,21 +4047,56 @@ static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, DEFUN (show_ip_ospf_neighbor_all, show_ip_ospf_neighbor_all_cmd, - "show ip ospf neighbor all [json]", + "show ip ospf [vrf ] neighbor all [json]", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Neighbor list\n" "include down status neighbor\n" JSON_STR) { struct ospf *ospf; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return show_ip_ospf_neighbor_all_common(vty, ospf, uj); + if (!uj) + show_ip_ospf_neighbour_header(vty); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_all_common(vty, + ospf, + uj); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } + + if (ospf) + ret = show_ip_ospf_neighbor_all_common(vty, ospf, uj); + + return ret; } DEFUN (show_ip_ospf_instance_neighbor_all, @@ -3926,8 +4137,6 @@ static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf, if (use_json) json = json_object_new_object(); - else - show_ip_ospf_neighbour_header(vty); if (ospf->instance) { if (use_json) @@ -3937,7 +4146,8 @@ static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf, vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); } - ifp = if_lookup_by_name(argv[arg_base]->arg, VRF_DEFAULT); + /*ifp = if_lookup_by_name(argv[arg_base]->arg, ospf->vrf_id);*/ + ifp = if_lookup_by_name_all_vrf(argv[arg_base]->arg); if (!ifp) { if (use_json) json_object_boolean_true_add(json, "noSuchIface"); @@ -3978,11 +4188,24 @@ DEFUN (show_ip_ospf_neighbor_int, struct ospf *ospf; int idx_ifname = 4; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + int ret = CMD_SUCCESS; + struct interface *ifp = NULL; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + if (!uj) + show_ip_ospf_neighbour_header(vty); - return show_ip_ospf_neighbor_int_common(vty, ospf, idx_ifname, argv, uj); + ifp = if_lookup_by_name_all_vrf(argv[idx_ifname]->arg); + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + if (!ifp || ifp->vrf_id != ospf->vrf_id) + continue; + ret = show_ip_ospf_neighbor_int_common(vty, ospf, + idx_ifname, argv, uj); + } + + return ret; } DEFUN (show_ip_ospf_instance_neighbor_int, @@ -4002,6 +4225,9 @@ DEFUN (show_ip_ospf_instance_neighbor_int, u_short instance = 0; u_char uj = use_json(argc, argv); + if (!uj) + show_ip_ospf_neighbour_header(vty); + instance = strtoul(argv[idx_number]->arg, NULL, 10); ospf = ospf_lookup_instance(instance); if (ospf == NULL) @@ -4010,6 +4236,9 @@ DEFUN (show_ip_ospf_instance_neighbor_int, if (!ospf->oi_running) return CMD_SUCCESS; + if (!uj) + show_ip_ospf_neighbour_header(vty); + return show_ip_ospf_neighbor_int_common(vty, ospf, idx_ifname, argv, uj); } @@ -4368,13 +4597,17 @@ DEFUN (show_ip_ospf_neighbor_id, JSON_STR) { struct ospf *ospf; - int idx_router_id = 4; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + int ret = CMD_SUCCESS; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj); + } - return show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id, argv, uj); + return ret; } DEFUN (show_ip_ospf_instance_neighbor_id, @@ -4453,21 +4686,53 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty, DEFUN (show_ip_ospf_neighbor_detail, show_ip_ospf_neighbor_detail_cmd, - "show ip ospf neighbor detail [json]", + "show ip ospf [vrf ] neighbor detail [json]", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Neighbor list\n" "detail of all neighbors\n" JSON_STR) { struct ospf *ospf; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return show_ip_ospf_neighbor_detail_common(vty, ospf, uj); + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_detail_common(vty, + ospf, + uj); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } + + if (ospf) + ret = show_ip_ospf_neighbor_detail_common(vty, ospf, uj); + + return ret; } DEFUN (show_ip_ospf_instance_neighbor_detail, @@ -4555,10 +4820,12 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty, DEFUN (show_ip_ospf_neighbor_detail_all, show_ip_ospf_neighbor_detail_all_cmd, - "show ip ospf neighbor detail all [json]", + "show ip ospf [vrf ] neighbor detail all [json]", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Neighbor list\n" "detail of all neighbors\n" "include down status neighbor\n" @@ -4566,11 +4833,41 @@ DEFUN (show_ip_ospf_neighbor_detail_all, { struct ospf *ospf; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj); + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_detail_all_common(vty, + ospf, + uj); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } + + if (ospf) + ret = show_ip_ospf_neighbor_detail_all_common(vty, ospf, uj); + + return ret; } DEFUN (show_ip_ospf_instance_neighbor_detail_all, @@ -4624,7 +4921,7 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty, vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); } - ifp = if_lookup_by_name(argv[arg_base]->arg, VRF_DEFAULT); + ifp = if_lookup_by_name_all_vrf(argv[arg_base]->arg); if (!ifp) { if (!use_json) vty_out(vty, "No such interface.\n"); @@ -4673,13 +4970,18 @@ DEFUN (show_ip_ospf_neighbor_int_detail, JSON_STR) { struct ospf *ospf; - int idx_ifname = 4; u_char uj = use_json(argc, argv); + struct listnode *node = NULL; + int ret = CMD_SUCCESS; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_int_detail_common(vty, ospf, 0, + argv, uj); + } - return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname, argv, uj); + return ret; } DEFUN (show_ip_ospf_instance_neighbor_int_detail, @@ -5356,29 +5658,62 @@ static int show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, DEFUN (show_ip_ospf_database_max, show_ip_ospf_database_max_cmd, - "show ip ospf database ", + "show ip ospf [vrf ] database ", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Database summary\n" "LSAs in MaxAge list\n" "Self-originated link states\n") { - struct ospf *ospf; + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return (show_ip_ospf_database_common(vty, ospf, 0, argc, argv)); + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_database_common(vty, ospf, + idx_vrf ? 2 + : 0, argc, + argv); + } + } else { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = (show_ip_ospf_database_common(vty, ospf, idx_vrf ? + 2 : 0, argc, argv)); + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_database_common(vty, ospf, 0, argc, argv); + } + + return ret; } DEFUN (show_ip_ospf_instance_database, show_ip_ospf_instance_database_cmd, - "show ip ospf [(1-65535)] database [ [A.B.C.D []]]", + "show ip ospf [{(1-65535)|vrf NAME}] database [ [A.B.C.D []]]", SHOW_STR IP_STR "OSPF information\n" "Instance ID\n" + VRF_CMD_HELP_STR "Database summary\n" OSPF_LSA_TYPES_DESC "Link State ID (as an IP address)\n" @@ -5388,22 +5723,53 @@ DEFUN (show_ip_ospf_instance_database, { struct ospf *ospf; u_short instance = 0; - + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; int idx = 0; + if (argv_find(argv, argc, "(1-65535)", &idx)) { instance = strtoul(argv[idx]->arg, NULL, 10); ospf = ospf_lookup_instance(instance); if (ospf == NULL) return CMD_NOT_MY_INSTANCE; - } else { - ospf = ospf_lookup(); + if (!ospf->oi_running) + return CMD_SUCCESS; + + return (show_ip_ospf_database_common(vty, ospf, idx ? 1 : 0, + argc, argv)); + } else if (argv_find(argv, argc, "vrf", &idx)) { + vrf_name = argv[++idx]->arg; + all_vrf = strmatch(vrf_name, "all"); } - if (!ospf || !ospf->oi_running) - return CMD_SUCCESS; + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = (show_ip_ospf_database_common(vty, ospf, + idx ? 2 : 0, + argc, argv)); + } + } else { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if ((ospf == NULL) || !ospf->oi_running) + return CMD_SUCCESS; + ret = (show_ip_ospf_database_common(vty, ospf, idx ? 2 : + 0, argc, argv)); + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = (show_ip_ospf_database_common(vty, ospf, 0, argc, argv)); + } - return (show_ip_ospf_database_common(vty, ospf, idx ? 1 : 0, argc, - argv)); + return ret; } DEFUN (show_ip_ospf_instance_database_max, @@ -5487,34 +5853,69 @@ static int show_ip_ospf_database_type_adv_router_common(struct vty *vty, DEFUN (show_ip_ospf_instance_database_type_adv_router, show_ip_ospf_instance_database_type_adv_router_cmd, - "show ip ospf [(1-65535)] database ", + "show ip ospf [{(1-65535)|vrf NAME}] database ", SHOW_STR IP_STR "OSPF information\n" "Instance ID\n" + VRF_CMD_HELP_STR "Database summary\n" OSPF_LSA_TYPES_DESC "Advertising Router link states\n" "Advertising Router (as an IP address)\n" "Self-originated link states\n") { - struct ospf *ospf; + struct ospf *ospf = NULL; u_short instance = 0; - int idx = 0; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx = 0, idx_vrf = 0; if (argv_find(argv, argc, "(1-65535)", &idx)) { instance = strtoul(argv[idx]->arg, NULL, 10); ospf = ospf_lookup_instance(instance); if (ospf == NULL) return CMD_NOT_MY_INSTANCE; - } else - ospf = ospf_lookup(); + if (!ospf->oi_running) + return CMD_SUCCESS; + return (show_ip_ospf_database_type_adv_router_common(vty, ospf, + idx ? 1 : 0, + argc, + argv)); + } - if (!ospf || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return (show_ip_ospf_database_type_adv_router_common( - vty, ospf, idx ? 1 : 0, argc, argv)); + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_database_type_adv_router_common(vty, + ospf, idx ? 1 : 0, argc, argv); + } + } else { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if ((ospf == NULL) || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_database_type_adv_router_common(vty, + ospf, idx ? 1 : 0, argc, argv); + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_database_type_adv_router_common(vty, ospf, + idx ? 1 : 0, + argc, argv); + } + return ret; + /*return (show_ip_ospf_database_type_adv_router_common( + vty, ospf, idx ? 1 : 0, argc, argv));*/ } DEFUN (ip_ospf_authentication_args, @@ -5994,13 +6395,14 @@ DEFUN (ip_ospf_cost, { VTY_DECLVAR_CONTEXT(interface, ifp); int idx = 0; - u_int32_t cost; + u_int32_t cost = OSPF_OUTPUT_COST_DEFAULT; struct in_addr addr; struct ospf_if_params *params; params = IF_DEF_PARAMS(ifp); // get arguments char *coststr = NULL, *ifaddr = NULL; + argv_find(argv, argc, "(1-65535)", &idx); coststr = argv[idx]->arg; cost = strtol(coststr, NULL, 10); @@ -6159,8 +6561,10 @@ static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str, /* Update timer values in neighbor structure. */ if (nbr_str) { - struct ospf *ospf; - if ((ospf = ospf_lookup())) { + struct ospf *ospf = NULL; + + ospf = ospf_lookup_by_vrf_id(ifp->vrf_id); + if (ospf) { oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr); if (oi) ospf_nbr_timer_update(oi); @@ -6271,9 +6675,10 @@ DEFUN (no_ip_ospf_dead_interval, /* Update timer values in neighbor structure. */ if (argc == 1) { - struct ospf *ospf; + struct ospf *ospf = NULL; - if ((ospf = ospf_lookup())) { + ospf = ospf_lookup_by_vrf_id(ifp->vrf_id); + if (ospf) { oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr); if (oi) ospf_nbr_timer_update(oi); @@ -6855,9 +7260,9 @@ DEFUN (ip_ospf_area, int format, ret; struct in_addr area_id; struct in_addr addr; - struct ospf_if_params *params; + struct ospf_if_params *params = NULL; struct route_node *rn; - struct ospf *ospf; + struct ospf *ospf = NULL; u_short instance = 0; char *areaid; @@ -6867,13 +7272,17 @@ DEFUN (ip_ospf_area, argv_find(argv, argc, "area", &idx); areaid = argv[idx + 1]->arg; - ospf = ospf_lookup_instance(instance); + if (ifp->vrf_id && !instance) + ospf = ospf_lookup_by_vrf_id(ifp->vrf_id); + else + ospf = ospf_lookup_instance(instance); + if (ospf == NULL) { params = IF_DEF_PARAMS(ifp); if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { UNSET_IF_PARAM(params, if_area); - ospf_interface_area_unset(ifp); - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + ospf_interface_area_unset(ospf, ifp); ospf->if_ospf_cli_count--; } return CMD_NOT_MY_INSTANCE; @@ -6922,10 +7331,12 @@ DEFUN (ip_ospf_area, } /* enable ospf on this interface with area_id */ - SET_IF_PARAM(params, if_area); - params->if_area = area_id; - params->if_area_id_fmt = format; - ospf_interface_area_set(ifp); + if (params) { + SET_IF_PARAM(params, if_area); + params->if_area = area_id; + params->if_area_id_fmt = format; + } + ospf_interface_area_set(ospf, ifp); ospf->if_ospf_cli_count++; return CMD_SUCCESS; @@ -6953,7 +7364,11 @@ DEFUN (no_ip_ospf_area, if (argv_find(argv, argc, "(1-65535)", &idx)) instance = strtol(argv[idx]->arg, NULL, 10); - ospf = ospf_lookup_instance(instance); + if (ifp->vrf_id && !instance) + ospf = ospf_lookup_by_vrf_id(ifp->vrf_id); + else + ospf = ospf_lookup_instance(instance); + if (ospf == NULL) return CMD_NOT_MY_INSTANCE; @@ -6983,7 +7398,7 @@ DEFUN (no_ip_ospf_area, ospf_if_update_params((ifp), (addr)); } - ospf_interface_area_unset(ifp); + ospf_interface_area_unset(ospf, ifp); ospf->if_ospf_cli_count--; return CMD_SUCCESS; } @@ -7657,7 +8072,7 @@ DEFUN (ospf_max_metric_router_lsa_startup, int idx_number = 3; unsigned int seconds; - if (argc != 1) { + if (argc < 4) { vty_out(vty, "%% Must supply stub-router period"); return CMD_WARNING_CONFIG_FAILED; } @@ -7713,7 +8128,7 @@ DEFUN (ospf_max_metric_router_lsa_shutdown, int idx_number = 3; unsigned int seconds; - if (argc != 1) { + if (argc < 4) { vty_out(vty, "%% Must supply stub-router shutdown period"); return CMD_WARNING_CONFIG_FAILED; } @@ -7762,7 +8177,8 @@ static void config_write_stub_router(struct vty *vty, struct ospf *ospf) return; } -static void show_ip_ospf_route_network(struct vty *vty, struct route_table *rt) +static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf, + struct route_table *rt) { struct route_node *rn; struct ospf_route * or ; @@ -7802,14 +8218,14 @@ static void show_ip_ospf_route_network(struct vty *vty, struct route_table *rt) for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode, path)) { if (if_lookup_by_index(path->ifindex, - VRF_DEFAULT)) { + ospf->vrf_id)) { if (path->nexthop.s_addr == 0) vty_out(vty, "%24s directly attached to %s\n", "", ifindex2ifname( path->ifindex, - VRF_DEFAULT)); + ospf->vrf_id)); else vty_out(vty, "%24s via %s, %s\n", @@ -7818,14 +8234,15 @@ static void show_ip_ospf_route_network(struct vty *vty, struct route_table *rt) path->nexthop), ifindex2ifname( path->ifindex, - VRF_DEFAULT)); + ospf->vrf_id)); } } } vty_out(vty, "\n"); } -static void show_ip_ospf_route_router(struct vty *vty, struct route_table *rtrs) +static void show_ip_ospf_route_router(struct vty *vty, struct ospf *ospf, + struct route_table *rtrs) { struct route_node *rn; struct ospf_route * or ; @@ -7864,14 +8281,14 @@ static void show_ip_ospf_route_router(struct vty *vty, struct route_table *rtrs) for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, path)) { if (if_lookup_by_index(path->ifindex, - VRF_DEFAULT)) { + ospf->vrf_id)) { if (path->nexthop.s_addr == 0) vty_out(vty, "%24s directly attached to %s\n", "", ifindex2ifname( path->ifindex, - VRF_DEFAULT)); + ospf->vrf_id)); else vty_out(vty, "%24s via %s, %s\n", @@ -7880,7 +8297,7 @@ static void show_ip_ospf_route_router(struct vty *vty, struct route_table *rtrs) path->nexthop), ifindex2ifname( path->ifindex, - VRF_DEFAULT)); + ospf->vrf_id)); } } } @@ -7888,7 +8305,8 @@ static void show_ip_ospf_route_router(struct vty *vty, struct route_table *rtrs) vty_out(vty, "\n"); } -static void show_ip_ospf_route_external(struct vty *vty, struct route_table *rt) +static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf, + struct route_table *rt) { struct route_node *rn; struct ospf_route *er; @@ -7921,14 +8339,14 @@ static void show_ip_ospf_route_external(struct vty *vty, struct route_table *rt) for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode, path)) { if (if_lookup_by_index(path->ifindex, - VRF_DEFAULT)) { + ospf->vrf_id)) { if (path->nexthop.s_addr == 0) vty_out(vty, "%24s directly attached to %s\n", "", ifindex2ifname( path->ifindex, - VRF_DEFAULT)); + ospf->vrf_id)); else vty_out(vty, "%24s via %s, %s\n", @@ -7937,7 +8355,7 @@ static void show_ip_ospf_route_external(struct vty *vty, struct route_table *rt) path->nexthop), ifindex2ifname( path->ifindex, - VRF_DEFAULT)); + ospf->vrf_id)); } } } @@ -7959,7 +8377,7 @@ static int show_ip_ospf_border_routers_common(struct vty *vty, show_ip_ospf_route_network (vty, ospf->new_table); */ /* Show Router routes. */ - show_ip_ospf_route_router(vty, ospf->new_rtrs); + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs); vty_out(vty, "\n"); @@ -7968,18 +8386,49 @@ static int show_ip_ospf_border_routers_common(struct vty *vty, DEFUN (show_ip_ospf_border_routers, show_ip_ospf_border_routers_cmd, - "show ip ospf border-routers", + "show ip ospf [vrf ] border-routers", SHOW_STR IP_STR "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" "Show all the ABR's and ASBR's\n") { - struct ospf *ospf; + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return show_ip_ospf_border_routers_common(vty, ospf); + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ret = show_ip_ospf_border_routers_common(vty, + ospf); + } + } else { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + + ret = show_ip_ospf_border_routers_common(vty, ospf); + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + ret = show_ip_ospf_border_routers_common(vty, ospf); + } + + return ret; } DEFUN (show_ip_ospf_instance_border_routers, @@ -8017,13 +8466,13 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf) } /* Show Network routes. */ - show_ip_ospf_route_network(vty, ospf->new_table); + show_ip_ospf_route_network(vty, ospf, ospf->new_table); /* Show Router routes. */ - show_ip_ospf_route_router(vty, ospf->new_rtrs); + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs); /* Show AS External routes. */ - show_ip_ospf_route_external(vty, ospf->old_external_route); + show_ip_ospf_route_external(vty, ospf, ospf->old_external_route); vty_out(vty, "\n"); @@ -8032,18 +8481,48 @@ static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf) DEFUN (show_ip_ospf_route, show_ip_ospf_route_cmd, - "show ip ospf route", - SHOW_STR - IP_STR - "OSPF information\n" - "OSPF routing table\n") + "show ip ospf [vrf ] route", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "OSPF routing table\n") { - struct ospf *ospf; + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = FALSE; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; - if ((ospf = ospf_lookup()) == NULL || !ospf->oi_running) - return CMD_SUCCESS; + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); - return show_ip_ospf_route_common(vty, ospf); + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_route_common(vty, ospf); + } + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) + return CMD_SUCCESS; + } + + if (ospf) + ret = show_ip_ospf_route_common(vty, ospf); + + return ret; } DEFUN (show_ip_ospf_instance_route, @@ -8070,6 +8549,77 @@ DEFUN (show_ip_ospf_instance_route, return show_ip_ospf_route_common(vty, ospf); } + +DEFUN (show_ip_ospf_vrfs, + show_ip_ospf_vrfs_cmd, + "show ip ospf vrfs [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Show OSPF VRFs \n" + JSON_STR) +{ + u_char uj = use_json(argc, argv); + json_object *json = NULL; + json_object *json_vrfs = NULL; + struct ospf *ospf = NULL; + struct listnode *node = NULL; + int count = 0; + static char header[] = "Name Id RouterId "; + + if (uj) { + json = json_object_new_object(); + json_vrfs = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + json_object *json_vrf = NULL; + const char *name = NULL; + int vrf_id_ui = 0; + + count++; + + if (!uj && count == 1) + vty_out(vty, "%s\n", header); + if (uj) + json_vrf = json_object_new_object(); + + if (ospf->vrf_id == 0) + name = VRF_DEFAULT_NAME; + else + name = ospf->name; + + vrf_id_ui = (ospf->vrf_id == VRF_UNKNOWN) ? -1 : ospf->vrf_id; + + if (uj) { + json_object_int_add(json_vrf, "vrfId", vrf_id_ui); + json_object_string_add(json_vrf, "routerId", + inet_ntoa(ospf->router_id)); + + json_object_object_add(json_vrfs, name, json_vrf); + + } else { + vty_out(vty, "%-25s %-5d %-16s \n", + name, ospf->vrf_id, inet_ntoa(ospf->router_id)); + } + } + + if (uj) { + json_object_object_add(json, "vrfs", json_vrfs); + json_object_int_add(json, "totalVrfs", count); + + vty_out(vty, "%s\n", json_object_to_json_string_ext(json, + JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else { + if (count) + vty_out(vty, "\nTotal number of OSPF VRFs (including default): %d\n", + count); + } + + return CMD_SUCCESS; +} + const char *ospf_abr_type_str[] = {"unknown", "standard", "ibm", "cisco", "shortcut"}; @@ -8081,26 +8631,32 @@ const char *ospf_int_type_str[] = {"unknown", /* should never be used. */ "virtual-link", /* should never be used. */ "loopback"}; -/* Configuration write function for ospfd. */ -static int config_write_interface(struct vty *vty) +static int config_write_interface_one(struct vty *vty, struct ospf *ospf) { struct listnode *n1, *n2; struct interface *ifp; struct crypt_key *ck; - int write = 0; struct route_node *rn = NULL; struct ospf_if_params *params; - struct ospf *ospf = ospf_lookup(); + int write = 0; + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), n1, ifp)) { + struct vrf *vrf = NULL; - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), n1, ifp)) { if (memcmp(ifp->name, "VLINK", 5) == 0) continue; if (ifp->ifindex == IFINDEX_DELETED) continue; + vrf = vrf_lookup_by_id(ifp->vrf_id); + vty_frame(vty, "!\n"); - vty_frame(vty, "interface %s\n", ifp->name); + if (ifp->vrf_id == VRF_DEFAULT || vrf == NULL) + vty_frame(vty, "interface %s\n", ifp->name); + else + vty_frame(vty, "interface %s vrf %s\n", + ifp->name, vrf->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -8115,11 +8671,11 @@ static int config_write_interface(struct vty *vty) if (params->type != ospf_default_iftype(ifp)) { vty_out(vty, " ip ospf network %s", ospf_int_type_str - [params->type]); + [params->type]); if (params != IF_DEF_PARAMS(ifp)) vty_out(vty, " %s", inet_ntoa( - rn->p.u.prefix4)); + rn->p.u.prefix4)); vty_out(vty, "\n"); } } @@ -8130,8 +8686,8 @@ static int config_write_interface(struct vty *vty) const char *auth_str; /* Translation tables are not that much help - here due to syntax - of the simple option */ + * here due to syntax + * of the simple option */ switch (params->auth_type) { case OSPF_AUTH_NULL: @@ -8171,18 +8727,22 @@ static int config_write_interface(struct vty *vty) } /* Cryptographic Authentication Key print. */ - for (ALL_LIST_ELEMENTS_RO(params->auth_crypt, n2, ck)) { - vty_out(vty, - " ip ospf message-digest-key %d md5 %s", - ck->key_id, ck->auth_key); - if (params != IF_DEF_PARAMS(ifp)) - vty_out(vty, " %s", - inet_ntoa(rn->p.u.prefix4)); - vty_out(vty, "\n"); + if (params && params->auth_crypt) { + for (ALL_LIST_ELEMENTS_RO(params->auth_crypt, + n2, ck)) { + vty_out(vty, + " ip ospf message-digest-key %d md5 %s", + ck->key_id, ck->auth_key); + if (params != IF_DEF_PARAMS(ifp)) + vty_out(vty, " %s", + inet_ntoa(rn->p.u.prefix4)); + vty_out(vty, "\n"); + } } /* Interface Output Cost print. */ - if (OSPF_IF_PARAM_CONFIGURED(params, output_cost_cmd)) { + if (OSPF_IF_PARAM_CONFIGURED(params, + output_cost_cmd)) { vty_out(vty, " ip ospf cost %u", params->output_cost_cmd); if (params != IF_DEF_PARAMS(ifp)) @@ -8206,7 +8766,7 @@ static int config_write_interface(struct vty *vty) /* Router Dead Interval print. */ if (OSPF_IF_PARAM_CONFIGURED(params, v_wait) && params->v_wait - != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT) { + != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT) { vty_out(vty, " ip ospf dead-interval "); /* fast hello ? */ @@ -8227,7 +8787,7 @@ static int config_write_interface(struct vty *vty) /* Router Priority print. */ if (OSPF_IF_PARAM_CONFIGURED(params, priority) && params->priority - != OSPF_ROUTER_PRIORITY_DEFAULT) { + != OSPF_ROUTER_PRIORITY_DEFAULT) { vty_out(vty, " ip ospf priority %u", params->priority); if (params != IF_DEF_PARAMS(ifp)) @@ -8240,7 +8800,7 @@ static int config_write_interface(struct vty *vty) if (OSPF_IF_PARAM_CONFIGURED(params, retransmit_interval) && params->retransmit_interval - != OSPF_RETRANSMIT_INTERVAL_DEFAULT) { + != OSPF_RETRANSMIT_INTERVAL_DEFAULT) { vty_out(vty, " ip ospf retransmit-interval %u", params->retransmit_interval); if (params != IF_DEF_PARAMS(ifp)) @@ -8252,7 +8812,7 @@ static int config_write_interface(struct vty *vty) /* Transmit Delay print. */ if (OSPF_IF_PARAM_CONFIGURED(params, transmit_delay) && params->transmit_delay - != OSPF_TRANSMIT_DELAY_DEFAULT) { + != OSPF_TRANSMIT_DELAY_DEFAULT) { vty_out(vty, " ip ospf transmit-delay %u", params->transmit_delay); if (params != IF_DEF_PARAMS(ifp)) @@ -8273,7 +8833,9 @@ static int config_write_interface(struct vty *vty) size_t buflen = MAX(strlen("4294967295"), strlen("255.255.255.255")); char buf[buflen]; - area_id2str(buf, sizeof(buf), ¶ms->if_area, + + area_id2str(buf, sizeof(buf), + ¶ms->if_area, params->if_area_id_fmt); vty_out(vty, " area %s", buf); if (params != IF_DEF_PARAMS(ifp)) @@ -8317,6 +8879,19 @@ static int config_write_interface(struct vty *vty) vty_endframe(vty, NULL); } + return write; +} + +/* Configuration write function for ospfd. */ +static int config_write_interface(struct vty *vty) +{ + int write = 0; + struct ospf *ospf = NULL; + struct listnode *node = NULL; + + /* Traverse all ospf [vrf] instances */ + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) + write += config_write_interface_one(vty, ospf); return write; } @@ -8657,154 +9232,174 @@ static int config_write_ospf_distance(struct vty *vty, struct ospf *ospf) return 0; } +static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) +{ + struct interface *ifp; + struct ospf_interface *oi; + struct listnode *node = NULL; + int write = 0; + + /* `router ospf' print. */ + if (ospf->instance && ospf->name) { + vty_out(vty, "router ospf %d vrf %s\n", + ospf->instance, ospf->name); + } else if (ospf->instance) { + vty_out(vty, "router ospf %d\n", + ospf->instance); + } else if (ospf->name) { + vty_out(vty, "router ospf vrf %s\n", + ospf->name); + } else + vty_out(vty, "router ospf\n"); + + if (!ospf->networks) { + write++; + return write; + } + + /* Router ID print. */ + if (ospf->router_id_static.s_addr != 0) + vty_out(vty, " ospf router-id %s\n", + inet_ntoa(ospf->router_id_static)); + + /* ABR type print. */ + if (ospf->abr_type != OSPF_ABR_DEFAULT) + vty_out(vty, " ospf abr-type %s\n", + ospf_abr_type_str[ospf->abr_type]); + + /* log-adjacency-changes flag print. */ + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) + vty_out(vty, " log-adjacency-changes detail\n"); + else if (!DFLT_OSPF_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes\n"); + } else if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) { + vty_out(vty, " no log-adjacency-changes\n"); + } + + /* RFC1583 compatibility flag print -- Compatible with CISCO + * 12.1. */ + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) + vty_out(vty, " compatible rfc1583\n"); + + /* auto-cost reference-bandwidth configuration. */ + if (ospf->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH) { + vty_out(vty, + "! Important: ensure reference bandwidth " + "is consistent across all routers\n"); + vty_out(vty, " auto-cost reference-bandwidth %d\n", + ospf->ref_bandwidth); + } + + /* SPF timers print. */ + if (ospf->spf_delay != OSPF_SPF_DELAY_DEFAULT + || ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT + || ospf->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) + vty_out(vty, " timers throttle spf %d %d %d\n", + ospf->spf_delay, ospf->spf_holdtime, + ospf->spf_max_holdtime); + + /* LSA timers print. */ + if (ospf->min_ls_interval != OSPF_MIN_LS_INTERVAL) + vty_out(vty, " timers throttle lsa all %d\n", + ospf->min_ls_interval); + if (ospf->min_ls_arrival != OSPF_MIN_LS_ARRIVAL) + vty_out(vty, " timers lsa min-arrival %d\n", + ospf->min_ls_arrival); + + /* Write multiplier print. */ + if (ospf->write_oi_count != OSPF_WRITE_INTERFACE_COUNT_DEFAULT) + vty_out(vty, " ospf write-multiplier %d\n", + ospf->write_oi_count); + + /* Max-metric router-lsa print */ + config_write_stub_router(vty, ospf); + + /* SPF refresh parameters print. */ + if (ospf->lsa_refresh_interval + != OSPF_LSA_REFRESH_INTERVAL_DEFAULT) + vty_out(vty, " refresh timer %d\n", + ospf->lsa_refresh_interval); + + /* Redistribute information print. */ + config_write_ospf_redistribute(vty, ospf); + + /* passive-interface print. */ + if (ospf->passive_interface_default == OSPF_IF_PASSIVE) + vty_out(vty, " passive-interface default\n"); + + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), node, ifp)) + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), + passive_interface) + && IF_DEF_PARAMS(ifp)->passive_interface + != ospf->passive_interface_default) { + vty_out(vty, " %spassive-interface %s\n", + IF_DEF_PARAMS(ifp)->passive_interface + ? "" + : "no ", + ifp->name); + } + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if (!OSPF_IF_PARAM_CONFIGURED(oi->params, + passive_interface)) + continue; + if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), + passive_interface)) { + if (oi->params->passive_interface + == IF_DEF_PARAMS(oi->ifp) + ->passive_interface) + continue; + } else if (oi->params->passive_interface + == ospf->passive_interface_default) + continue; + + vty_out(vty, " %spassive-interface %s %s\n", + oi->params->passive_interface ? "" : "no ", + oi->ifp->name, + inet_ntoa(oi->address->u.prefix4)); + } + + /* Network area print. */ + config_write_network_area(vty, ospf); + + /* Area config print. */ + config_write_ospf_area(vty, ospf); + + /* static neighbor print. */ + config_write_ospf_nbr_nbma(vty, ospf); + + /* Virtual-Link print. */ + config_write_virtual_link(vty, ospf); + + /* Default metric configuration. */ + config_write_ospf_default_metric(vty, ospf); + + /* Distribute-list and default-information print. */ + config_write_ospf_distribute(vty, ospf); + + /* Distance configuration. */ + config_write_ospf_distance(vty, ospf); + + ospf_opaque_config_write_router(vty, ospf); + + write++; + return write; +} + /* OSPF configuration write function. */ static int ospf_config_write(struct vty *vty) { struct ospf *ospf; - struct interface *ifp; - struct ospf_interface *oi; - struct listnode *node; + struct listnode *ospf_node = NULL; int write = 0; - ospf = ospf_lookup(); - if (ospf != NULL && ospf->oi_running) { - /* `router ospf' print. */ - if (ospf->instance) - vty_out(vty, "router ospf %d\n", ospf->instance); - else - vty_out(vty, "router ospf\n"); + if (listcount(om->ospf) == 0) + return write; - write++; - - if (!ospf->networks) - return write; - - /* Router ID print. */ - if (ospf->router_id_static.s_addr != 0) - vty_out(vty, " ospf router-id %s\n", - inet_ntoa(ospf->router_id_static)); - - /* ABR type print. */ - if (ospf->abr_type != OSPF_ABR_DEFAULT) - vty_out(vty, " ospf abr-type %s\n", - ospf_abr_type_str[ospf->abr_type]); - - /* log-adjacency-changes flag print. */ - if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { - if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) - vty_out(vty, " log-adjacency-changes detail\n"); - else if (!DFLT_OSPF_LOG_ADJACENCY_CHANGES) - vty_out(vty, " log-adjacency-changes\n"); - } else if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) { - vty_out(vty, " no log-adjacency-changes\n"); - } - - /* RFC1583 compatibility flag print -- Compatible with CISCO - * 12.1. */ - if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) - vty_out(vty, " compatible rfc1583\n"); - - /* auto-cost reference-bandwidth configuration. */ - if (ospf->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH) { - vty_out(vty, - "! Important: ensure reference bandwidth " - "is consistent across all routers\n"); - vty_out(vty, " auto-cost reference-bandwidth %d\n", - ospf->ref_bandwidth); - } - - /* SPF timers print. */ - if (ospf->spf_delay != OSPF_SPF_DELAY_DEFAULT - || ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT - || ospf->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) - vty_out(vty, " timers throttle spf %d %d %d\n", - ospf->spf_delay, ospf->spf_holdtime, - ospf->spf_max_holdtime); - - /* LSA timers print. */ - if (ospf->min_ls_interval != OSPF_MIN_LS_INTERVAL) - vty_out(vty, " timers throttle lsa all %d\n", - ospf->min_ls_interval); - if (ospf->min_ls_arrival != OSPF_MIN_LS_ARRIVAL) - vty_out(vty, " timers lsa min-arrival %d\n", - ospf->min_ls_arrival); - - /* Write multiplier print. */ - if (ospf->write_oi_count != OSPF_WRITE_INTERFACE_COUNT_DEFAULT) - vty_out(vty, " ospf write-multiplier %d\n", - ospf->write_oi_count); - - /* Max-metric router-lsa print */ - config_write_stub_router(vty, ospf); - - /* SPF refresh parameters print. */ - if (ospf->lsa_refresh_interval - != OSPF_LSA_REFRESH_INTERVAL_DEFAULT) - vty_out(vty, " refresh timer %d\n", - ospf->lsa_refresh_interval); - - /* Redistribute information print. */ - config_write_ospf_redistribute(vty, ospf); - - /* passive-interface print. */ - if (ospf->passive_interface_default == OSPF_IF_PASSIVE) - vty_out(vty, " passive-interface default\n"); - - for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) - if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), - passive_interface) - && IF_DEF_PARAMS(ifp)->passive_interface - != ospf->passive_interface_default) { - vty_out(vty, " %spassive-interface %s\n", - IF_DEF_PARAMS(ifp)->passive_interface - ? "" - : "no ", - ifp->name); - } - for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { - if (!OSPF_IF_PARAM_CONFIGURED(oi->params, - passive_interface)) - continue; - if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), - passive_interface)) { - if (oi->params->passive_interface - == IF_DEF_PARAMS(oi->ifp) - ->passive_interface) - continue; - } else if (oi->params->passive_interface - == ospf->passive_interface_default) - continue; - - vty_out(vty, " %spassive-interface %s %s\n", - oi->params->passive_interface ? "" : "no ", - oi->ifp->name, - inet_ntoa(oi->address->u.prefix4)); - } - - /* Network area print. */ - config_write_network_area(vty, ospf); - - /* Area config print. */ - config_write_ospf_area(vty, ospf); - - /* static neighbor print. */ - config_write_ospf_nbr_nbma(vty, ospf); - - /* Virtual-Link print. */ - config_write_virtual_link(vty, ospf); - - /* Default metric configuration. */ - config_write_ospf_default_metric(vty, ospf); - - /* Distribute-list and default-information print. */ - config_write_ospf_distribute(vty, ospf); - - /* Distance configuration. */ - config_write_ospf_distance(vty, ospf); - - ospf_opaque_config_write_router(vty, ospf); + for (ALL_LIST_ELEMENTS_RO(om->ospf, ospf_node, ospf)) { + if (ospf->oi_running) + write += ospf_config_write_one(vty, ospf); } - return write; } @@ -8853,6 +9448,9 @@ void ospf_vty_show_init(void) install_element(VIEW_NODE, &show_ip_ospf_instance_route_cmd); install_element(VIEW_NODE, &show_ip_ospf_instance_border_routers_cmd); + + /* "show ip ospf vrfs" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_vrfs_cmd); } @@ -8993,17 +9591,20 @@ DEFUN (clear_ip_ospf_interface, { int idx_ifname = 4; struct interface *ifp; - struct listnode *node; + struct listnode *node, *n1; + struct ospf *ospf = NULL; if (argc == 4) /* Clear all the ospfv2 interfaces. */ { - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) - ospf_interface_clear(ifp); - } else /* Interface name is specified. */ - { - if ((ifp = if_lookup_by_name(argv[idx_ifname]->arg, - VRF_DEFAULT)) - == NULL) + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), + node, ifp)) + ospf_interface_clear(ifp); + } + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name_all_vrf(argv[idx_ifname]->arg); + if (ifp == NULL) vty_out(vty, "No such interface name\n"); else ospf_interface_clear(ifp); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 9bba2c9806..d8fd9afbd7 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -53,6 +53,7 @@ DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table") DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute") +DEFINE_MTYPE_STATIC(OSPFD, OSPF_DIST_ARGS, "OSPF Distribute arguments") DEFINE_HOOK(ospf_if_update, (struct interface * ifp), (ifp)) DEFINE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp)) @@ -68,23 +69,33 @@ struct in_addr router_id_zebra; static int ospf_router_id_update_zebra(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct ospf *ospf; + struct ospf *ospf = NULL; struct prefix router_id; zebra_router_id_update_read(zclient->ibuf, &router_id); if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { char buf[PREFIX2STR_BUFFER]; prefix2str(&router_id, buf, sizeof(buf)); - zlog_debug("Zebra rcvd: router id update %s", buf); + zlog_debug("Zebra rcvd: router id update %s vrf %s id %u", + buf, ospf_vrf_id_to_name(vrf_id), vrf_id); } router_id_zebra = router_id.u.prefix4; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(vrf_id); if (ospf != NULL) ospf_router_id_update(ospf); + else { + if (IS_DEBUG_OSPF_EVENT) { + char buf[PREFIX2STR_BUFFER]; + prefix2str(&router_id, buf, sizeof(buf)); + zlog_debug("%s: ospf instance not found for vrf %s id %u router_id %s", + __PRETTY_FUNCTION__, + ospf_vrf_id_to_name(vrf_id), vrf_id, buf); + } + } return 0; } @@ -92,14 +103,18 @@ static int ospf_router_id_update_zebra(int command, struct zclient *zclient, static int ospf_interface_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { - struct interface *ifp; + struct interface *ifp = NULL; + struct ospf *ospf = NULL; ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); + if (ifp == NULL) + return 0; if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) zlog_debug( - "Zebra: interface add %s[%u] index %d flags %llx metric %d mtu %d", - ifp->name, ifp->vrf_id, ifp->ifindex, + "Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d", + ifp->name, ospf_vrf_id_to_name(ifp->vrf_id), + ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); assert(ifp->info); @@ -109,7 +124,11 @@ static int ospf_interface_add(int command, struct zclient *zclient, IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); } - ospf_if_update(NULL, ifp); + ospf = ospf_lookup_by_vrf_id(vrf_id); + if (!ospf) + return 0; + + ospf_if_update(ospf, ifp); hook_call(ospf_if_update, ifp); @@ -136,8 +155,9 @@ static int ospf_interface_delete(int command, struct zclient *zclient, if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) zlog_debug( - "Zebra: interface delete %s[%u] index %d flags %llx metric %d mtu %d", - ifp->name, ifp->vrf_id, ifp->ifindex, + "Zebra: interface delete %s vrf %s[%u] index %d flags %llx metric %d mtu %d", + ifp->name, ospf_vrf_id_to_name(ifp->vrf_id), + ifp->vrf_id, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); hook_call(ospf_if_delete, ifp); @@ -160,7 +180,7 @@ static struct interface *zebra_interface_if_lookup(struct stream *s, /* And look it up. */ return if_lookup_by_name_len( - ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), VRF_DEFAULT); + ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ), vrf_id); } static int ospf_interface_state_up(int command, struct zclient *zclient, @@ -249,6 +269,8 @@ static int ospf_interface_address_add(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { struct connected *c; + struct ospf *ospf = NULL; + c = zebra_interface_address_read(command, zclient->ibuf, vrf_id); @@ -258,11 +280,16 @@ static int ospf_interface_address_add(int command, struct zclient *zclient, if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) { char buf[PREFIX2STR_BUFFER]; prefix2str(c->address, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s address add %s", c->ifp->name, - buf); + zlog_debug("Zebra: interface %s address add %s vrf %s id %u", + c->ifp->name, buf, ospf_vrf_id_to_name(vrf_id), + vrf_id); } - ospf_if_update(NULL, c->ifp); + ospf = ospf_lookup_by_vrf_id(vrf_id); + if (!ospf) + return 0; + + ospf_if_update(ospf, c->ifp); hook_call(ospf_if_update, c->ifp); @@ -330,19 +357,41 @@ static int ospf_interface_link_params(int command, struct zclient *zclient, return 0; } +/* VRF update for an interface. */ +static int ospf_interface_vrf_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct interface *ifp = NULL; + vrf_id_t new_vrf_id; -void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) + ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id, + &new_vrf_id); + if (!ifp) + return 0; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Rx Interface %s VRF change vrf_id %u New vrf %s id %u", + __PRETTY_FUNCTION__, ifp->name, vrf_id, + ospf_vrf_id_to_name(new_vrf_id), new_vrf_id); + + /*if_update(ifp, ifp->name, strlen(ifp->name), new_vrf_id);*/ + if_update_to_new_vrf(ifp, new_vrf_id); + + return 0; +} + +void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p, + struct ospf_route *or) { struct zapi_route api; struct zapi_nexthop *api_nh; u_char distance; struct ospf_path *path; struct listnode *node; - struct ospf *ospf = ospf_lookup(); int count = 0; memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = ospf->vrf_id; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; api.safi = SAFI_UNICAST; @@ -368,7 +417,7 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) } /* Distance value. */ - distance = ospf_distance_apply(p, or); + distance = ospf_distance_apply(ospf, p, or); if (distance) { SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); api.distance = distance; @@ -413,13 +462,13 @@ void ospf_zebra_add(struct prefix_ipv4 *p, struct ospf_route * or) zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); } -void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) +void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p, + struct ospf_route *or) { struct zapi_route api; - struct ospf *ospf = ospf_lookup(); memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = ospf->vrf_id; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; api.safi = SAFI_UNICAST; @@ -435,13 +484,12 @@ void ospf_zebra_delete(struct prefix_ipv4 *p, struct ospf_route * or) zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); } -void ospf_zebra_add_discard(struct prefix_ipv4 *p) +void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p) { struct zapi_route api; - struct ospf *ospf = ospf_lookup(); memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = ospf->vrf_id; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; api.safi = SAFI_UNICAST; @@ -455,13 +503,12 @@ void ospf_zebra_add_discard(struct prefix_ipv4 *p) inet_ntoa(p->prefix), p->prefixlen); } -void ospf_zebra_delete_discard(struct prefix_ipv4 *p) +void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p) { struct zapi_route api; - struct ospf *ospf = ospf_lookup(); memset(&api, 0, sizeof(api)); - api.vrf_id = VRF_DEFAULT; + api.vrf_id = ospf->vrf_id; api.type = ZEBRA_ROUTE_OSPF; api.instance = ospf->instance; api.safi = SAFI_UNICAST; @@ -595,11 +642,11 @@ void ospf_redist_del(struct ospf *ospf, u_char type, u_short instance) } -int ospf_is_type_redistributed(int type, u_short instance) +int ospf_is_type_redistributed(struct ospf *ospf, int type, u_short instance) { return (DEFAULT_ROUTE_TYPE(type) ? vrf_bitmap_check(zclient->default_information, - VRF_DEFAULT) + ospf->vrf_id) : ((instance && redist_check_instance( &zclient->mi_redist[AFI_IP][type], @@ -607,7 +654,7 @@ int ospf_is_type_redistributed(int type, u_short instance) || (!instance && vrf_bitmap_check( zclient->redist[AFI_IP][type], - VRF_DEFAULT)))); + ospf->vrf_id)))); } int ospf_redistribute_set(struct ospf *ospf, int type, u_short instance, @@ -617,7 +664,7 @@ int ospf_redistribute_set(struct ospf *ospf, int type, u_short instance, struct ospf_redist *red; red = ospf_redist_lookup(ospf, type, instance); - if (ospf_is_type_redistributed(type, instance)) { + if (ospf_is_type_redistributed(ospf, type, instance)) { if (mtype != red->dmetric.type) { red->dmetric.type = mtype; force = LSA_REFRESH_FORCE; @@ -645,11 +692,11 @@ int ospf_redistribute_set(struct ospf *ospf, int type, u_short instance, ospf_external_add(type, instance); zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, - instance, VRF_DEFAULT); + instance, ospf->vrf_id); if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Redistribute[%s][%d]: Start Type[%d], Metric[%d]", - ospf_redist_string(type), instance, + zlog_debug("Redistribute[%s][%d] vrf id %u: Start Type[%d], Metric[%d]", + ospf_redist_string(type), instance, ospf->vrf_id, metric_type(ospf, type, instance), metric_value(ospf, type, instance)); @@ -663,15 +710,15 @@ int ospf_redistribute_unset(struct ospf *ospf, int type, u_short instance) if (type == zclient->redist_default && instance == zclient->instance) return CMD_SUCCESS; - if (!ospf_is_type_redistributed(type, instance)) + if (!ospf_is_type_redistributed(ospf, type, instance)) return CMD_SUCCESS; zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, - instance, VRF_DEFAULT); + instance, ospf->vrf_id); if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Redistribute[%s][%d]: Stop", - ospf_redist_string(type), instance); + zlog_debug("Redistribute[%s][%d] vrf id %u: Stop", + ospf_redist_string(type), instance, ospf->vrf_id); ospf_redist_del(ospf, type, instance); @@ -698,7 +745,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, ospf_external_add(DEFAULT_ROUTE, 0); - if (ospf_is_type_redistributed(DEFAULT_ROUTE, 0)) { + if (ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) { /* if ospf->default_originate changes value, is calling ospf_external_lsa_refresh_default sufficient to implement the change? */ @@ -714,7 +761,7 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, } zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, - VRF_DEFAULT); + ospf->vrf_id); if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", @@ -734,14 +781,14 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, int ospf_redistribute_default_unset(struct ospf *ospf) { - if (!ospf_is_type_redistributed(DEFAULT_ROUTE, 0)) + if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) return CMD_SUCCESS; ospf->default_originate = DEFAULT_ORIGINATE_NONE; ospf_redist_del(ospf, DEFAULT_ROUTE, 0); zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, - VRF_DEFAULT); + ospf->vrf_id); if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug("Redistribute[DEFAULT]: Stop"); @@ -886,7 +933,7 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, struct ospf *ospf; int i; - ospf = ospf_lookup(); + ospf = ospf_lookup_by_vrf_id(vrf_id); if (ospf == NULL) return 0; @@ -1019,10 +1066,13 @@ static int ospf_distribute_list_update_timer(struct thread *thread) struct external_info *ei; struct route_table *rt; struct ospf_lsa *lsa; - int type, default_refresh = 0; - struct ospf *ospf; + int type, default_refresh = 0, arg_type; + struct ospf *ospf = NULL; + void **arg = THREAD_ARG (thread); + + ospf = (struct ospf *)arg[0]; + arg_type = (int)(intptr_t)arg[1]; - ospf = ospf_lookup(); if (ospf == NULL) return 0; @@ -1030,6 +1080,12 @@ static int ospf_distribute_list_update_timer(struct thread *thread) zlog_info("Zebra[Redistribute]: distribute-list update timer fired!"); + if (IS_DEBUG_OSPF_EVENT) { + zlog_debug("%s: ospf distribute-list update arg_type %d vrf %s id %d", + __PRETTY_FUNCTION__, arg_type, + ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id); + } + /* foreach all external info. */ for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { struct list *ext_list; @@ -1062,15 +1118,21 @@ static int ospf_distribute_list_update_timer(struct thread *thread) } if (default_refresh) ospf_external_lsa_refresh_default(ospf); + + XFREE(MTYPE_OSPF_DIST_ARGS, arg); return 0; } /* Update distribute-list and set timer to apply access-list. */ -void ospf_distribute_list_update(struct ospf *ospf, uintptr_t type, +void ospf_distribute_list_update(struct ospf *ospf, int type, u_short instance) { struct route_table *rt; struct ospf_external *ext; + void **args = XCALLOC(MTYPE_OSPF_DIST_ARGS, sizeof(void *)*2); + + args[0] = ospf; + args[1] = (void *)((ptrdiff_t) type); /* External info does not exist. */ ext = ospf_external_lookup(type, instance); @@ -1084,7 +1146,7 @@ void ospf_distribute_list_update(struct ospf *ospf, uintptr_t type, /* Set timer. */ ospf->t_distribute_update = NULL; thread_add_timer_msec(master, ospf_distribute_list_update_timer, - (void *)type, ospf->min_ls_interval, + (void **)args, ospf->min_ls_interval, &ospf->t_distribute_update); } @@ -1095,134 +1157,148 @@ static void ospf_filter_update(struct access_list *access) int type; int abr_inv = 0; struct ospf_area *area; - struct listnode *node; + struct listnode *node, *n1; /* If OSPF instance does not exist, return right now. */ - ospf = ospf_lookup(); - if (ospf == NULL) + if (listcount(om->ospf) == 0) return; - /* Update distribute-list, and apply filter. */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; + /* Iterate all ospf [VRF] instances */ + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { + /* Update distribute-list, and apply filter. */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; - red_list = ospf->redist[type]; - if (red_list) - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { - if (ROUTEMAP(red)) { - /* if route-map is not NULL it may be - * using this access list */ - ospf_distribute_list_update( - ospf, type, red->instance); + red_list = ospf->redist[type]; + if (red_list) + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + if (ROUTEMAP(red)) { + /* if route-map is not NULL it may be + * using this access list */ + ospf_distribute_list_update( + ospf, + type, red->instance); + } } + + /* There is place for route-map for default-information + * (ZEBRA_ROUTE_MAX), + * but no distribute list. */ + if (type == ZEBRA_ROUTE_MAX) + break; + + if (DISTRIBUTE_NAME(ospf, type)) { + /* Keep old access-list for distribute-list. */ + struct access_list *old = DISTRIBUTE_LIST(ospf, + type); + + /* Update access-list for distribute-list. */ + DISTRIBUTE_LIST(ospf, type) = access_list_lookup( + AFI_IP, DISTRIBUTE_NAME(ospf, type)); + + /* No update for this distribute type. */ + if (old == NULL && DISTRIBUTE_LIST(ospf, type) == NULL) + continue; + + /* Schedule distribute-list update timer. */ + if (DISTRIBUTE_LIST(ospf, type) == NULL + || strcmp(DISTRIBUTE_NAME(ospf, type), access->name) + == 0) + ospf_distribute_list_update(ospf, type, 0); + } + } + + /* Update Area access-list. */ + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (EXPORT_NAME(area)) { + EXPORT_LIST(area) = NULL; + abr_inv++; } - /* There is place for route-map for default-information - * (ZEBRA_ROUTE_MAX), - * but no distribute list. */ - if (type == ZEBRA_ROUTE_MAX) - break; - - if (DISTRIBUTE_NAME(ospf, type)) { - /* Keep old access-list for distribute-list. */ - struct access_list *old = DISTRIBUTE_LIST(ospf, type); - - /* Update access-list for distribute-list. */ - DISTRIBUTE_LIST(ospf, type) = access_list_lookup( - AFI_IP, DISTRIBUTE_NAME(ospf, type)); - - /* No update for this distribute type. */ - if (old == NULL && DISTRIBUTE_LIST(ospf, type) == NULL) - continue; - - /* Schedule distribute-list update timer. */ - if (DISTRIBUTE_LIST(ospf, type) == NULL - || strcmp(DISTRIBUTE_NAME(ospf, type), access->name) - == 0) - ospf_distribute_list_update(ospf, type, 0); + if (IMPORT_NAME(area)) { + IMPORT_LIST(area) = NULL; + abr_inv++; + } } + + /* Schedule ABR tasks -- this will be changed -- takada. */ + if (IS_OSPF_ABR(ospf) && abr_inv) + ospf_schedule_abr_task(ospf); } - - /* Update Area access-list. */ - for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { - if (EXPORT_NAME(area)) { - EXPORT_LIST(area) = NULL; - abr_inv++; - } - - if (IMPORT_NAME(area)) { - IMPORT_LIST(area) = NULL; - abr_inv++; - } - } - - /* Schedule ABR tasks -- this will be changed -- takada. */ - if (IS_OSPF_ABR(ospf) && abr_inv) - ospf_schedule_abr_task(ospf); } /* If prefix-list is updated, do some updates. */ void ospf_prefix_list_update(struct prefix_list *plist) { - struct ospf *ospf; + struct ospf *ospf = NULL; int type; int abr_inv = 0; struct ospf_area *area; - struct listnode *node; + struct listnode *node, *n1; /* If OSPF instatnce does not exist, return right now. */ - ospf = ospf_lookup(); - if (ospf == NULL) + if (listcount(om->ospf) == 0) return; - /* Update all route-maps which are used as redistribution filters. - * They might use prefix-list. - */ - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { - struct list *red_list; - struct listnode *node; - struct ospf_redist *red; + /* Iterate all ospf [VRF] instances */ + for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { - red_list = ospf->redist[type]; - if (red_list) - for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { - if (ROUTEMAP(red)) { - /* if route-map is not NULL it may be - * using this prefix list */ - ospf_distribute_list_update( - ospf, type, red->instance); + /* Update all route-maps which are used + * as redistribution filters. + * They might use prefix-list. + */ + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + red_list = ospf->redist[type]; + if (red_list) { + for (ALL_LIST_ELEMENTS_RO(red_list, + node, red)) { + if (ROUTEMAP(red)) { + /* if route-map is not NULL + * it may be using + * this prefix list */ + ospf_distribute_list_update( + ospf, type, + red->instance); + } } } + } + + /* Update area filter-lists. */ + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + /* Update filter-list in. */ + if (PREFIX_NAME_IN(area)) + if (strcmp(PREFIX_NAME_IN(area), + prefix_list_name(plist)) == 0) { + PREFIX_LIST_IN(area) = + prefix_list_lookup( + AFI_IP, + PREFIX_NAME_IN(area)); + abr_inv++; + } + + /* Update filter-list out. */ + if (PREFIX_NAME_OUT(area)) + if (strcmp(PREFIX_NAME_OUT(area), + prefix_list_name(plist)) == 0) { + PREFIX_LIST_IN(area) = + prefix_list_lookup( + AFI_IP, + PREFIX_NAME_OUT(area)); + abr_inv++; + } + } + + /* Schedule ABR task. */ + if (IS_OSPF_ABR(ospf) && abr_inv) + ospf_schedule_abr_task(ospf); } - - /* Update area filter-lists. */ - for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { - /* Update filter-list in. */ - if (PREFIX_NAME_IN(area)) - if (strcmp(PREFIX_NAME_IN(area), - prefix_list_name(plist)) - == 0) { - PREFIX_LIST_IN(area) = prefix_list_lookup( - AFI_IP, PREFIX_NAME_IN(area)); - abr_inv++; - } - - /* Update filter-list out. */ - if (PREFIX_NAME_OUT(area)) - if (strcmp(PREFIX_NAME_OUT(area), - prefix_list_name(plist)) - == 0) { - PREFIX_LIST_IN(area) = prefix_list_lookup( - AFI_IP, PREFIX_NAME_OUT(area)); - abr_inv++; - } - } - - /* Schedule ABR task. */ - if (IS_OSPF_ABR(ospf) && abr_inv) - ospf_schedule_abr_task(ospf); } static struct ospf_distance *ospf_distance_new(void) @@ -1326,11 +1402,10 @@ void ospf_distance_reset(struct ospf *ospf) } } -u_char ospf_distance_apply(struct prefix_ipv4 *p, struct ospf_route * or) +u_char ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p, + struct ospf_route *or) { - struct ospf *ospf; - ospf = ospf_lookup(); if (ospf == NULL) return 0; @@ -1353,6 +1428,37 @@ u_char ospf_distance_apply(struct prefix_ipv4 *p, struct ospf_route * or) return 0; } +void ospf_zebra_vrf_register(struct ospf *ospf) +{ + if (!zclient || zclient->sock < 0 || !ospf) + return; + + if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Register VRF %s id %u", + __PRETTY_FUNCTION__, + ospf_vrf_id_to_name(ospf->vrf_id), + ospf->vrf_id); + zclient_send_reg_requests(zclient, ospf->vrf_id); + } +} + +void ospf_zebra_vrf_deregister(struct ospf *ospf) +{ + if (!zclient || zclient->sock < 0 || !ospf) + return; + + if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: De-Register VRF %s id %u", + __PRETTY_FUNCTION__, + ospf_vrf_id_to_name(ospf->vrf_id), + ospf->vrf_id); + /* Deregister for router-id, interfaces, + * redistributed routes. */ + zclient_send_dereg_requests(zclient, ospf->vrf_id); + } +} static void ospf_zebra_connected(struct zclient *zclient) { /* Send the client registration */ @@ -1375,6 +1481,7 @@ void ospf_zebra_init(struct thread_master *master, u_short instance) zclient->interface_address_add = ospf_interface_address_add; zclient->interface_address_delete = ospf_interface_address_delete; zclient->interface_link_params = ospf_interface_link_params; + zclient->interface_vrf_update = ospf_interface_vrf_update; zclient->redistribute_route_add = ospf_zebra_read_route; zclient->redistribute_route_del = ospf_zebra_read_route; diff --git a/ospfd/ospf_zebra.h b/ospfd/ospf_zebra.h index 6fa9e33ddd..8340f49ede 100644 --- a/ospfd/ospf_zebra.h +++ b/ospfd/ospf_zebra.h @@ -41,21 +41,24 @@ struct ospf_distance { }; /* Prototypes */ -extern void ospf_zebra_add(struct prefix_ipv4 *, struct ospf_route *); -extern void ospf_zebra_delete(struct prefix_ipv4 *, struct ospf_route *); +extern void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *, + struct ospf_route *); +extern void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *, + struct ospf_route *); -extern void ospf_zebra_add_discard(struct prefix_ipv4 *); -extern void ospf_zebra_delete_discard(struct prefix_ipv4 *); +extern void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *); +extern void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *); extern int ospf_redistribute_check(struct ospf *, struct external_info *, int *); extern int ospf_distribute_check_connected(struct ospf *, struct external_info *); -extern void ospf_distribute_list_update(struct ospf *, uintptr_t, u_short); +extern void ospf_distribute_list_update(struct ospf *, int, u_short); -extern int ospf_is_type_redistributed(int, u_short); +extern int ospf_is_type_redistributed(struct ospf *, int, u_short); extern void ospf_distance_reset(struct ospf *); -extern u_char ospf_distance_apply(struct prefix_ipv4 *, struct ospf_route *); +extern u_char ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *, + struct ospf_route *); extern struct ospf_external *ospf_external_lookup(u_char, u_short); extern struct ospf_external *ospf_external_add(u_char, u_short); extern void ospf_external_del(u_char, u_short); @@ -77,6 +80,8 @@ extern int ospf_distance_set(struct vty *, struct ospf *, const char *, extern int ospf_distance_unset(struct vty *, struct ospf *, const char *, const char *, const char *); extern void ospf_zebra_init(struct thread_master *, u_short); +extern void ospf_zebra_vrf_register(struct ospf *ospf); +extern void ospf_zebra_vrf_deregister(struct ospf *ospf); DECLARE_HOOK(ospf_if_update, (struct interface * ifp), (ifp)) DECLARE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp)) diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index ed1d8901fb..507c97d979 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -67,6 +67,7 @@ struct ospf_master *om; extern struct zclient *zclient; extern struct in_addr router_id_zebra; +extern struct zebra_privs_t ospfd_privs; static void ospf_remove_vls_through_area(struct ospf *, struct ospf_area *); @@ -118,6 +119,10 @@ void ospf_router_id_update(struct ospf *ospf) else router_id = router_id_zebra; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("Router-ID[OLD:%s]: Update to %s", + inet_ntoa(ospf->router_id), + inet_ntoa(router_id_old)); if (!IPV4_ADDR_SAME(&router_id_old, &router_id)) { @@ -204,7 +209,7 @@ void ospf_router_id_update(struct ospf *ospf) ospf_router_lsa_update(ospf); /* update ospf_interface's */ - for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), node, ifp)) ospf_if_update(ospf, ifp); } } @@ -220,9 +225,10 @@ static int ospf_area_id_cmp(struct ospf_area *a1, struct ospf_area *a2) } /* Allocate new ospf structure. */ -static struct ospf *ospf_new(u_short instance) +static struct ospf *ospf_new(u_short instance, const char *name) { int i; + struct vrf *vrf = NULL; struct ospf *new = XCALLOC(MTYPE_OSPF_TOP, sizeof(struct ospf)); @@ -230,6 +236,23 @@ static struct ospf *ospf_new(u_short instance) new->router_id.s_addr = htonl(0); new->router_id_static.s_addr = htonl(0); + if (name) { + new->vrf_id = VRF_UNKNOWN; + /* Freed in ospf_finish_final */ + new->name = XSTRDUP(MTYPE_OSPF_TOP, name); + vrf = vrf_lookup_by_name(new->name); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: Create new ospf instance with vrf_name %s vrf_id %d", + __PRETTY_FUNCTION__, name, new->vrf_id); + if (vrf) + ospf_vrf_link(new, vrf); + } else { + new->vrf_id = VRF_DEFAULT; + vrf = vrf_lookup_by_id(VRF_DEFAULT); + ospf_vrf_link(new, vrf); + } + ospf_zebra_vrf_register(new); + new->abr_type = OSPF_ABR_DEFAULT; new->oiflist = list_new(); new->vlinks = list_new(); @@ -286,7 +309,7 @@ static struct ospf *ospf_new(u_short instance) new->lsa_refresh_interval, &new->t_lsa_refresher); new->lsa_refresher_started = monotime(NULL); - if ((new->fd = ospf_sock_init()) < 0) { + if ((ospf_sock_init(new)) < 0) { zlog_err( "ospf_new: fatal error: ospf_sock_init was unable to open " "a socket"); @@ -313,14 +336,6 @@ static struct ospf *ospf_new(u_short instance) return new; } -struct ospf *ospf_lookup() -{ - if (listcount(om->ospf) == 0) - return NULL; - - return listgetdata((struct listnode *)listhead(om->ospf)); -} - struct ospf *ospf_lookup_instance(u_short instance) { struct ospf *ospf; @@ -357,13 +372,33 @@ static void ospf_delete(struct ospf *ospf) listnode_delete(om->ospf, ospf); } -struct ospf *ospf_get() +struct ospf *ospf_lookup_by_inst_name(u_short instance, const char *name) +{ + struct ospf *ospf = NULL; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) { + if ((ospf->instance == instance) && + ((ospf->name == NULL && name == NULL) || + (ospf->name && name && strcmp(ospf->name, name) == 0))) + return ospf; + } + return NULL; +} + +struct ospf *ospf_get(u_short instance, const char *name) { struct ospf *ospf; - ospf = ospf_lookup(); + /* vrf name provided call inst and name based api + * in case of no name pass default ospf instance */ + if (name) + ospf = ospf_lookup_by_inst_name(instance, name); + else + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL) { - ospf = ospf_new(0); + ospf = ospf_new(instance, name); ospf_add(ospf); if (ospf->router_id_static.s_addr == 0) @@ -381,11 +416,20 @@ struct ospf *ospf_get_instance(u_short instance) ospf = ospf_lookup_instance(instance); if (ospf == NULL) { - ospf = ospf_new(instance); + ospf = ospf_new(instance, NULL /* VRF_DEFAULT*/); ospf_add(ospf); - if (ospf->router_id_static.s_addr == 0) + if (ospf->router_id_static.s_addr == 0) { + if (vrf_lookup_by_id(ospf->vrf_id)) + ospf_router_id_update(ospf); + else { + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ospf VRF (id %d) is not active yet, skip router id update" + , __PRETTY_FUNCTION__, + ospf->vrf_id); + } ospf_router_id_update(ospf); + } ospf_opaque_type11_lsa_init(ospf); } @@ -393,6 +437,34 @@ struct ospf *ospf_get_instance(u_short instance) return ospf; } +struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id) +{ + struct vrf *vrf = NULL; + + vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) + return NULL; + return (vrf->info) ? (struct ospf *)vrf->info : NULL; + +} + +/* It should only be used when processing incoming info update from zebra. + * Other situations, it is not sufficient to lookup the ospf instance by + * vrf_name only without using the instance number. + */ +static struct ospf *ospf_lookup_by_name(const char *vrf_name) +{ + struct ospf *ospf = NULL; + struct listnode *node, *nnode; + + for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) + if ((ospf->name == NULL && vrf_name == NULL) + || (ospf->name && vrf_name && + strcmp(ospf->name, vrf_name) == 0)) + return ospf; + return NULL; +} + /* Handle the second half of deferred shutdown. This is called either * from the deferred-shutdown timer thread, or directly through * ospf_deferred_shutdown_check. @@ -519,6 +591,7 @@ static void ospf_finish_final(struct ospf *ospf) struct listnode *node, *nnode; int i; u_short instance = 0; + struct vrf *vrf = NULL; QOBJ_UNREG(ospf); @@ -550,7 +623,7 @@ static void ospf_finish_final(struct ospf *ospf) list_delete(ospf->vlinks); /* Remove any ospf interface config params */ - for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(ospf->vrf_id), node, ifp)) { struct ospf_if_params *params; params = IF_DEF_PARAMS(ifp); @@ -562,6 +635,9 @@ static void ospf_finish_final(struct ospf *ospf) for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) ospf_if_free(oi); + /* De-Register VRF */ + ospf_zebra_vrf_deregister(ospf); + /* Clear static neighbors */ for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn)) if ((nbr_nbma = rn->info)) { @@ -639,7 +715,7 @@ static void ospf_finish_final(struct ospf *ospf) if (ospf->old_table) ospf_route_table_free(ospf->old_table); if (ospf->new_table) { - ospf_route_delete(ospf->new_table); + ospf_route_delete(ospf, ospf->new_table); ospf_route_table_free(ospf->new_table); } if (ospf->old_rtrs) @@ -647,11 +723,11 @@ static void ospf_finish_final(struct ospf *ospf) if (ospf->new_rtrs) ospf_rtrs_free(ospf->new_rtrs); if (ospf->new_external_route) { - ospf_route_delete(ospf->new_external_route); + ospf_route_delete(ospf, ospf->new_external_route); ospf_route_table_free(ospf->new_external_route); } if (ospf->old_external_route) { - ospf_route_delete(ospf->old_external_route); + ospf_route_delete(ospf, ospf->old_external_route); ospf_route_table_free(ospf->old_external_route); } if (ospf->external_lsas) { @@ -694,6 +770,17 @@ static void ospf_finish_final(struct ospf *ospf) ospf_delete(ospf); + if (ospf->name) { + vrf = vrf_lookup_by_name(ospf->name); + if (vrf) + ospf_vrf_unlink(ospf, vrf); + XFREE(MTYPE_OSPF_TOP, ospf->name); + } else { + vrf = vrf_lookup_by_id(VRF_DEFAULT); + if (vrf) + ospf_vrf_unlink(ospf, vrf); + } + XFREE(MTYPE_OSPF_TOP, ospf); if (!CHECK_FLAG(om->options, OSPF_MASTER_SHUTDOWN)) @@ -883,7 +970,7 @@ static void update_redistributed(struct ospf *ospf, int add_to_ospf) struct external_info *ei; struct ospf_external *ext; - if (ospf_is_type_redistributed(ZEBRA_ROUTE_CONNECT, 0)) + if (ospf_is_type_redistributed(ospf, ZEBRA_ROUTE_CONNECT, 0)) if ((ext = ospf_external_lookup(ZEBRA_ROUTE_CONNECT, 0)) && EXTERNAL_INFO(ext)) { for (rn = route_top(EXTERNAL_INFO(ext)); rn; @@ -1004,9 +1091,10 @@ int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p, * * Otherwise, doesn't do anything different to ospf_if_update for now */ -void ospf_interface_area_set(struct interface *ifp) +void ospf_interface_area_set(struct ospf *ospf, struct interface *ifp) { - struct ospf *ospf = ospf_get(); + if (!ospf) + return; ospf_if_update(ospf, ifp); /* if_update does a update_redistributed */ @@ -1014,19 +1102,17 @@ void ospf_interface_area_set(struct interface *ifp) return; } -void ospf_interface_area_unset(struct interface *ifp) +void ospf_interface_area_unset(struct ospf *ospf, struct interface *ifp) { struct route_node *rn_oi; - struct ospf *ospf; - ospf = ospf_lookup(); if (!ospf) return; /* Ospf not ready yet */ /* Find interfaces that may need to be removed. */ for (rn_oi = route_top(IF_OIFS(ifp)); rn_oi; rn_oi = route_next(rn_oi)) { - struct ospf_interface *oi; + struct ospf_interface *oi = NULL; if ((oi = rn_oi->info) == NULL) continue; @@ -1174,7 +1260,7 @@ static void ospf_network_run(struct prefix *p, struct ospf_area *area) ospf_router_id_update(area->ospf); /* Get target interface. */ - for (ALL_LIST_ELEMENTS_RO(om->iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO(vrf_iflist(area->ospf->vrf_id), node, ifp)) ospf_network_run_interface(area->ospf, ifp, p, area); } @@ -1203,8 +1289,15 @@ void ospf_ls_upd_queue_empty(struct ospf_interface *oi) void ospf_if_update(struct ospf *ospf, struct interface *ifp) { + if (!ospf) - ospf = ospf_lookup(); + return; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: interface %s ifp->vrf_id %u ospf vrf %s vrf_id %u router_id %s", + __PRETTY_FUNCTION__, ifp->name, ifp->vrf_id, + ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id, + inet_ntoa(ospf->router_id)); /* OSPF must be ready. */ if (!ospf_is_ready(ospf)) @@ -1863,3 +1956,128 @@ void ospf_master_init(struct thread_master *master) om->ospf = list_new(); om->master = master; } + +/* Link OSPF instance to VRF. */ +void ospf_vrf_link(struct ospf *ospf, struct vrf *vrf) +{ + ospf->vrf_id = vrf->vrf_id; + if (vrf->info != (void *)ospf) + vrf->info = (void *)ospf; +} + +/* Unlink OSPF instance from VRF. */ +void ospf_vrf_unlink(struct ospf *ospf, struct vrf *vrf) +{ + if (vrf->info == (void *)ospf) + vrf->info = NULL; + ospf->vrf_id = VRF_UNKNOWN; +} + +/* This is hook function for vrf create called as part of vrf_init */ +static int ospf_vrf_new(struct vrf *vrf) +{ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: VRF Created: %s(%d)", __PRETTY_FUNCTION__, + vrf->name, vrf->vrf_id); + + return 0; +} + +/* This is hook function for vrf delete call as part of vrf_init */ +static int ospf_vrf_delete(struct vrf *vrf) +{ + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: VRF Deletion: %s(%d)", __PRETTY_FUNCTION__, + vrf->name, vrf->vrf_id); + + return 0; +} + +/* Enable OSPF VRF instance */ +static int ospf_vrf_enable(struct vrf *vrf) +{ + struct ospf *ospf = NULL; + vrf_id_t old_vrf_id = VRF_DEFAULT; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: VRF %s id %d enabled", + __PRETTY_FUNCTION__, vrf->name, vrf->vrf_id); + + ospf = ospf_lookup_by_name(vrf->name); + if (ospf) { + old_vrf_id = ospf->vrf_id; + /* We have instance configured, link to VRF and make it "up". */ + ospf_vrf_link(ospf, vrf); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ospf linked to vrf %s vrf_id %d (old id %d)", + __PRETTY_FUNCTION__, vrf->name, ospf->vrf_id, + old_vrf_id); + + if (old_vrf_id != ospf->vrf_id) { + if (ospfd_privs.change(ZPRIVS_RAISE)) { + zlog_err("ospf_sock_init: could not raise privs, %s", + safe_strerror(errno)); + } + if (ospf_bind_vrfdevice(ospf, ospf->fd) < 0) + return 0; + if (ospfd_privs.change(ZPRIVS_LOWER)) { + zlog_err("ospf_sock_init: could not lower privs, %s", + safe_strerror(errno)); + } + + ospf->oi_running = 1; + ospf_router_id_update(ospf); + } + } + + return 0; +} + +/* Disable OSPF VRF instance */ +static int ospf_vrf_disable(struct vrf *vrf) +{ + struct ospf *ospf = NULL; + vrf_id_t old_vrf_id = VRF_UNKNOWN; + + if (vrf->vrf_id == VRF_DEFAULT) + return 0; + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: VRF %s id %d disabled.", + __PRETTY_FUNCTION__, vrf->name, vrf->vrf_id); + + ospf = ospf_lookup_by_name(vrf->name); + if (ospf) { + old_vrf_id = ospf->vrf_id; + + /* We have instance configured, unlink + * from VRF and make it "down". + */ + ospf_vrf_unlink(ospf, vrf); + ospf->oi_running = 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug("%s: ospf old_vrf_id %d unlinked", + __PRETTY_FUNCTION__, old_vrf_id); + } + + /* Note: This is a callback, the VRF will be deleted by the caller. */ + return 0; +} + +void ospf_vrf_init(void) +{ + vrf_init(ospf_vrf_new, ospf_vrf_enable, + ospf_vrf_disable, ospf_vrf_delete); +} + +void ospf_vrf_terminate(void) +{ + vrf_terminate(); +} + +const char *ospf_vrf_id_to_name(vrf_id_t vrf_id) +{ + struct vrf *vrf = vrf_lookup_by_id(vrf_id); + + return vrf ? vrf->name : "NIL"; +} diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index b49bbdc17d..01147c2004 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -28,6 +28,7 @@ #include "filter.h" #include "log.h" +#include "vrf.h" #include "ospf_memory.h" #include "ospf_dump_api.h" @@ -92,8 +93,6 @@ struct ospf_master { /* OSPF thread master. */ struct thread_master *master; - /* Zebra interface list. */ - struct list *iflist; /* Redistributed external information. */ struct list *external[ZEBRA_ROUTE_MAX + 1]; @@ -136,6 +135,9 @@ struct ospf { struct in_addr router_id; /* Configured automatically. */ struct in_addr router_id_static; /* Configured manually. */ + vrf_id_t vrf_id; /* VRF Id */ + char *name; /* VRF name */ + /* ABR/ASBR internal flags. */ u_char flags; #define OSPF_FLAG_ABR 0x0001 @@ -503,10 +505,12 @@ extern int ospf_zlog; /* Prototypes. */ extern const char *ospf_redist_string(u_int route_type); -extern struct ospf *ospf_lookup(void); extern struct ospf *ospf_lookup_instance(u_short); -extern struct ospf *ospf_get(void); +extern struct ospf *ospf_get(u_short instance, const char *name); extern struct ospf *ospf_get_instance(u_short); +extern struct ospf *ospf_lookup_by_inst_name(u_short instance, + const char *name); +extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id); extern void ospf_finish(struct ospf *); extern void ospf_router_id_update(struct ospf *ospf); extern int ospf_network_set(struct ospf *, struct prefix_ipv4 *, struct in_addr, @@ -559,11 +563,15 @@ extern struct ospf_area *ospf_area_lookup_by_area_id(struct ospf *, extern void ospf_area_add_if(struct ospf_area *, struct ospf_interface *); extern void ospf_area_del_if(struct ospf_area *, struct ospf_interface *); -extern void ospf_interface_area_set(struct interface *); -extern void ospf_interface_area_unset(struct interface *); +extern void ospf_interface_area_set(struct ospf *, struct interface *); +extern void ospf_interface_area_unset(struct ospf *, struct interface *); extern void ospf_route_map_init(void); extern void ospf_master_init(struct thread_master *master); - +extern void ospf_vrf_init(void); +extern void ospf_vrf_terminate(void); +extern void ospf_vrf_link(struct ospf *ospf, struct vrf *vrf); +extern void ospf_vrf_unlink(struct ospf *ospf, struct vrf *vrf); +const char *ospf_vrf_id_to_name(vrf_id_t vrf_id); #endif /* _ZEBRA_OSPFD_H */ diff --git a/ospfd/subdir.am b/ospfd/subdir.am index 12c2313e65..e063415fbd 100644 --- a/ospfd/subdir.am +++ b/ospfd/subdir.am @@ -58,6 +58,9 @@ ospfdheader_HEADERS = \ # end endif +ospfd/ospf_vty_clippy.c: $(CLIPPY_DEPS) +ospfd/ospf_vty.$(OBJEXT): ospfd/ospf_vty_clippy.c + noinst_HEADERS += \ ospfd/ospf_abr.h \ ospfd/ospf_apiserver.h \ diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 73440461ec..061c25cea5 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1273,10 +1273,12 @@ DEFUNSH(VTYSH_RIPNGD, router_ripng, router_ripng_cmd, "router ripng", return CMD_SUCCESS; } -DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd, "router ospf [(1-65535)]", +DEFUNSH(VTYSH_OSPFD, router_ospf, router_ospf_cmd, + "router ospf [(1-65535)] [vrf NAME]", "Enable a routing process\n" "Start OSPF configuration\n" - "Instance ID\n") + "Instance ID\n" + VRF_CMD_HELP_STR) { vty->node = OSPF_NODE; return CMD_SUCCESS;