#include #include "lib/stream.h" #include "lib/vty.h" #include "lib/mpls.h" #include "lib/if.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_spf.h" #include "ospfd/ospf_flood.h" #include "ospfd/ospf_lsa.h" #include "ospfd/ospf_lsdb.h" #include "ospfd/ospf_interface.h" #include "ospfd/ospf_sr.h" #include "common.h" struct thread_master *master; struct zebra_privs_t ospfd_privs; struct ospf_topology *test_find_topology(const char *name) { if (strmatch(name, "topo1")) return &topo1; else if (strmatch(name, "topo2")) return &topo2; else if (strmatch(name, "topo3")) return &topo3; return NULL; } struct ospf_test_node *test_find_node(struct ospf_topology *topology, const char *hostname) { for (int i = 0; topology->nodes[i].hostname[0]; i++) if (strmatch(hostname, topology->nodes[i].hostname)) return &topology->nodes[i]; return NULL; } static void inject_router_lsa(struct vty *vty, struct ospf *ospf, struct ospf_topology *topology, struct ospf_test_node *root, struct ospf_test_node *tnode) { struct ospf_area *area; struct in_addr router_id; struct in_addr adj_router_id; struct prefix_ipv4 prefix; struct in_addr data; struct stream *s; struct lsa_header *lsah; struct ospf_lsa *new; int length; unsigned long putp; uint16_t link_count; struct ospf_test_node *tfound_adj_node; struct ospf_test_adj *tadj; bool is_self_lsa = false; area = ospf->backbone; inet_aton(tnode->router_id, &router_id); if (strncmp(root->router_id, tnode->router_id, 256) == 0) is_self_lsa = true; s = stream_new(OSPF_MAX_LSA_SIZE); lsa_header_set(s, LSA_OPTIONS_GET(area) | LSA_OPTIONS_NSSA_GET(area), OSPF_ROUTER_LSA, router_id, router_id); stream_putc(s, router_lsa_flags(area)); stream_putc(s, 0); putp = stream_get_endp(s); stream_putw(s, 0); for (link_count = 0; tnode->adjacencies[link_count].hostname[0]; link_count++) { tadj = &tnode->adjacencies[link_count]; tfound_adj_node = test_find_node(topology, tadj->hostname); str2prefix_ipv4(tnode->adjacencies[link_count].network, &prefix); inet_aton(tfound_adj_node->router_id, &adj_router_id); data.s_addr = prefix.prefix.s_addr; link_info_set(&s, adj_router_id, data, LSA_LINK_TYPE_POINTOPOINT, 0, tadj->metric); masklen2ip(prefix.prefixlen, &data); link_info_set(&s, prefix.prefix, data, LSA_LINK_TYPE_STUB, 0, tadj->metric); } /* Don't forget the node itself (just a stub) */ str2prefix_ipv4(tnode->router_id, &prefix); data.s_addr = 0xffffffff; link_info_set(&s, prefix.prefix, data, LSA_LINK_TYPE_STUB, 0, 0); /* Take twice the link count (for P2P and stub) plus the local stub */ stream_putw_at(s, putp, (2 * link_count) + 1); length = stream_get_endp(s); lsah = (struct lsa_header *)STREAM_DATA(s); lsah->length = htons(length); new = ospf_lsa_new_and_data(length); new->area = area; new->vrf_id = area->ospf->vrf_id; if (is_self_lsa) SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); memcpy(new->data, lsah, length); stream_free(s); ospf_lsdb_add(area->lsdb, new); if (is_self_lsa) { ospf_lsa_unlock(&area->router_lsa_self); area->router_lsa_self = ospf_lsa_lock(new); } } static void inject_sr_db_entry(struct vty *vty, struct ospf_test_node *tnode) { struct in_addr router_id; struct sr_node *srn; struct sr_prefix *srp; inet_aton(tnode->router_id, &router_id); srn = ospf_sr_node_create(&router_id); srn->srgb.range_size = 8000; srn->srgb.lower_bound = 16000; srn->msd = 16; srp = XCALLOC(MTYPE_OSPF_SR_PARAMS, sizeof(struct sr_prefix)); srp->adv_router = router_id; srp->sid = tnode->label; srp->srn = srn; listnode_add(srn->ext_prefix, srp); } int topology_load(struct vty *vty, struct ospf_topology *topology, struct ospf_test_node *root, struct ospf *ospf) { struct ospf_test_node *tnode; for (int i = 0; topology->nodes[i].hostname[0]; i++) { tnode = &topology->nodes[i]; /* Inject a router LSA for each node, used for SPF */ inject_router_lsa(vty, ospf, topology, root, tnode); /* * SR information could also be inected via LSAs, but directly * filling the SR DB with labels is just easier. */ inject_sr_db_entry(vty, tnode); } return 0; }