📄 ospf_lsa.c
字号:
link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost); } else { /* Option 2: We need to include link to a stub network regardless of the state of the neighbor */ masklen2ip (oi->address->prefixlen, &mask); id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost); } links++; return links;}/* Describe Broadcast Link. */intlsa_link_broadcast_set (struct stream *s, struct ospf_interface *oi){ struct ospf_neighbor *dr; struct in_addr id, mask; /* Describe Type 3 Link. */ if (oi->state == ISM_Waiting) { masklen2ip (oi->address->prefixlen, &mask); id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost); return 1; } dr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi)); /* Describe Type 2 link. */ if (dr && (dr->state == NSM_Full || IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi))) && ospf_nbr_count (oi, NSM_Full) > 0) { link_info_set (s, DR (oi), oi->address->u.prefix4, LSA_LINK_TYPE_TRANSIT, 0, oi->output_cost); } /* Describe type 3 link. */ else { masklen2ip (oi->address->prefixlen, &mask); id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost); } return 1;}intlsa_link_loopback_set (struct stream *s, struct ospf_interface *oi){ struct in_addr id, mask; /* Describe Type 3 Link. */ if (oi->state != ISM_Loopback) return 0; mask.s_addr = 0xffffffff; id.s_addr = oi->address->u.prefix4.s_addr; link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, oi->output_cost); return 1;}/* Describe Virtual Link. */intlsa_link_virtuallink_set (struct stream *s, struct ospf_interface *oi){ struct ospf_neighbor *nbr; if (oi->state == ISM_PointToPoint) if ((nbr = ospf_nbr_lookup_ptop (oi))) if (nbr->state == NSM_Full) { link_info_set (s, nbr->router_id, oi->address->u.prefix4, LSA_LINK_TYPE_VIRTUALLINK, 0, oi->output_cost); return 1; } return 0;}#define lsa_link_nbma_set(S,O) lsa_link_broadcast_set (S, O)/* This function add for support point-to-multipoint ,see RFC2328 12.4.1.4.*/intlsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi){ int links = 0; struct route_node *rn; struct ospf_neighbor *nbr = NULL; struct in_addr id, mask; mask.s_addr = 0xffffffff; id.s_addr = oi->address->u.prefix4.s_addr; link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, 0); links++; zlog_info ("PointToMultipoint: running ptomultip_set"); /* Search neighbor, */ for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) if ((nbr = rn->info) != NULL) /* Ignore myself. */ if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id)) if (nbr->state == NSM_Full) { link_info_set (s, nbr->router_id, oi->address->u.prefix4, LSA_LINK_TYPE_POINTOPOINT, 0, oi->output_cost); links++; zlog_info ("PointToMultipoint: set link to %s", inet_ntoa(oi->address->u.prefix4)); } return links;}/* Set router-LSA link information. */introuter_lsa_link_set (struct stream *s, struct ospf_area *area){ listnode node; int links = 0; for (node = listhead (area->oiflist); node; node = nextnode (node)) { struct ospf_interface *oi = node->data; struct interface *ifp = oi->ifp; /* Check interface is up, OSPF is enable. */ if (if_is_up (ifp)) { if (oi->state != ISM_Down) { /* Describe each link. */ switch (oi->type) { case OSPF_IFTYPE_POINTOPOINT: links += lsa_link_ptop_set (s, oi); break; case OSPF_IFTYPE_BROADCAST: links += lsa_link_broadcast_set (s, oi); break; case OSPF_IFTYPE_NBMA: links += lsa_link_nbma_set (s, oi); break; case OSPF_IFTYPE_POINTOMULTIPOINT: links += lsa_link_ptomp_set (s, oi); break; case OSPF_IFTYPE_VIRTUALLINK: links += lsa_link_virtuallink_set (s, oi); break; case OSPF_IFTYPE_LOOPBACK: links += lsa_link_loopback_set (s, oi); } } } } return links;}/* Set router-LSA body. */voidospf_router_lsa_body_set (struct stream *s, struct ospf_area *area){ unsigned long putp; u_int16_t cnt; /* Set flags. */ stream_putc (s, router_lsa_flags (area)); /* Set Zero fields. */ stream_putc (s, 0); /* Keep pointer to # links. */ putp = s->putp; /* Forward word */ stream_putw(s, 0); /* Set all link information. */ cnt = router_lsa_link_set (s, area); /* Set # of links here. */ stream_putw_at (s, putp, cnt);}/* Create new router-LSA. */struct ospf_lsa *ospf_router_lsa_new (struct ospf_area *area){ struct ospf *ospf = area->ospf; struct stream *s; struct lsa_header *lsah; struct ospf_lsa *new; int length; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type1]: Create router-LSA instance"); /* Create a stream for LSA. */ s = stream_new (OSPF_MAX_LSA_SIZE); lsah = (struct lsa_header *) STREAM_DATA (s);#ifdef HAVE_NSSA /* Set LSA common header fields. */ lsa_header_set (s, LSA_OPTIONS_GET (area) | LSA_NSSA_GET (area), OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);#else /* ! HAVE_NSSA */ /* Set LSA common header fields. */ lsa_header_set (s, LSA_OPTIONS_GET (area), OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id);#endif /* HAVE_NSSA */ /* Set router-LSA body fields. */ ospf_router_lsa_body_set (s, area); /* Set length. */ length = stream_get_endp (s); lsah->length = htons (length); /* Now, create OSPF LSA instance. */ new = ospf_lsa_new (); new->area = area; SET_FLAG (new->flags, OSPF_LSA_SELF); /* Copy LSA data to store, discard stream. */ new->data = ospf_lsa_data_new (length); memcpy (new->data, lsah, length); stream_free (s); return new;}/* Originate Router-LSA. */struct ospf_lsa *ospf_router_lsa_originate (struct ospf_area *area){ struct ospf_lsa *new; /* Create new router-LSA instance. */ new = ospf_router_lsa_new (area); /* Sanity check. */ if (new->data->adv_router.s_addr == 0) { if (IS_DEBUG_OSPF_EVENT) zlog_info ("LSA[Type1]: AdvRouter is 0, discard"); ospf_lsa_discard (new); return NULL; } /* Install LSA to LSDB. */ new = ospf_lsa_install (area->ospf, NULL, new); /* Update LSA origination count. */ area->ospf->lsa_originate_count++; /* Flooding new LSA through area. */ ospf_flood_through_area (area, NULL, new); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: Originate router-LSA %p", new->data->type, inet_ntoa (new->data->id), new); ospf_lsa_header_dump (new->data); } return new;}/* Refresh router-LSA. */struct ospf_lsa *ospf_router_lsa_refresh (struct ospf_lsa *lsa){ struct ospf_area *area = lsa->area; struct ospf_lsa *new; /* Sanity check. */ assert (lsa->data); /* Delete LSA from neighbor retransmit-list. */ ospf_ls_retransmit_delete_nbr_area (area, lsa); /* Create new router-LSA instance. */ new = ospf_router_lsa_new (area); new->data->ls_seqnum = lsa_seqnum_increment (lsa); ospf_lsa_install (area->ospf, NULL, new); /* Flood LSA through area. */ ospf_flood_through_area (area, NULL, new); /* Debug logging. */ if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: router-LSA refresh", new->data->type, inet_ntoa (new->data->id)); ospf_lsa_header_dump (new->data); } return NULL;}intospf_router_lsa_timer (struct thread *t){ struct ospf_area *area; if (IS_DEBUG_OSPF_EVENT) zlog_info ("Timer[router-LSA]: (router-LSA Refresh expire)"); area = THREAD_ARG (t); area->t_router_lsa_self = NULL; /* Now refresh router-LSA. */ if (area->router_lsa_self) ospf_router_lsa_refresh (area->router_lsa_self); /* Newly originate router-LSA. */ else ospf_router_lsa_originate (area); return 0;}voidospf_router_lsa_timer_add (struct ospf_area *area){ /* Keep area's self-originated router-LSA. */ struct ospf_lsa *lsa = area->router_lsa_self; /* Cancel previously scheduled router-LSA timer. */ if (area->t_router_lsa_self) if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type1]: Cancel previous router-LSA timer"); OSPF_TIMER_OFF (area->t_router_lsa_self); /* If router-LSA is originated previously, check the interval time. */ if (lsa) { int delay; if ((delay = ospf_lsa_refresh_delay (lsa)) > 0) { OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, delay); return; } } if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type1]: Scheduling router-LSA origination right away"); /* Immediately refresh router-LSA. */ OSPF_AREA_TIMER_ON (area->t_router_lsa_self, ospf_router_lsa_timer, 0);}intospf_router_lsa_update_timer (struct thread *thread){ struct ospf *ospf = THREAD_ARG (thread); listnode node; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("Timer[router-LSA Update]: (timer expire)"); ospf->t_router_lsa_update = NULL; for (node = listhead (ospf->areas); node; nextnode (node)) { struct ospf_area *area = getdata (node); struct ospf_lsa *lsa = area->router_lsa_self; struct router_lsa *rl; char *area_str; /* Keep Area ID string. */ area_str = AREA_NAME (area); /* If LSA not exist in this Area, originate new. */ if (lsa == NULL) { if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info("LSA[Type1]: Create router-LSA for Area %s", area_str); ospf_router_lsa_originate (area); } /* If router-ID is changed, Link ID must change. First flush old LSA, then originate new. */ else if (!IPV4_ADDR_SAME (&lsa->data->id, &ospf->router_id)) { if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info("LSA[Type%d:%s]: Refresh router-LSA for Area %s", lsa->data->type, inet_ntoa (lsa->data->id), area_str); ospf_lsa_flush_area (lsa, area); ospf_lsa_unlock (area->router_lsa_self); area->router_lsa_self = NULL; /* Refresh router-LSA, (not install) and flood through area. */ ospf_router_lsa_timer_add (area); } else { rl = (struct router_lsa *) lsa->data; /* Refresh router-LSA, (not install) and flood through area. */ if (rl->flags != ospf->flags) ospf_router_lsa_timer_add (area); } } return 0;}/* network-LSA related functions. *//* Originate Network-LSA. */voidospf_network_lsa_body_set (struct stream *s, struct ospf_interface *oi){ struct in_addr mask; struct route_node *rn; struct ospf_neighbor *nbr; masklen2ip (oi->address->prefixlen, &mask); stream_put_ipv4 (s, mask.s_addr); /* The network-LSA lists those routers that are fully adjacent to the Designated Router; each fully adjacent router is identified by its OSPF Router ID. The Designated Router includes itself in this list. RFC2328, Section 12.4.2 */ for (rn = route_top (oi->nbrs); rn; rn = route_next (rn)) if ((nbr = rn->info) != NULL) if (nbr->state == NSM_Full || nbr == oi->nbr_self) stream_put_ipv4 (s, nbr->router_id.s_addr);}struct ospf_lsa *ospf_network_lsa_new (struct ospf_interface *oi){ struct stream *s; struct ospf_lsa *new; struct lsa_header *lsah; int length; /* If there are no neighbours on this network (the net is stub), the router does not originate network-LSA (see RFC 12.4.2) */ if (oi->full_nbrs == 0) return NULL; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type2]: Create network-LSA instance"); /* Create new stream for LSA. */ s = stream_new (OSPF_MAX_LSA_SIZE); lsah = (struct lsa_header *) STREAM_DATA (s); lsa_header_set (s, (OPTIONS (oi) | LSA_OPTIONS_GET (oi->area)), OSPF_NETWORK_LSA, DR (oi), oi->ospf->router_id); /* Set network-LSA body fields. */ ospf_network_lsa_body_set (s, oi); /* Set length. */ length = stream_get_endp (s); lsah->length = htons (length); /* Create OSPF LSA instance. */ new = ospf_lsa_new (); new->area = oi->area; SET_FLAG (new->flags, OSPF_LSA_SELF); /* Copy LSA to store. */ new->data = ospf_lsa_data_new (length); memcpy (new->data, lsah, length); stream_free (s); return new;}/* Originate network-LSA. */struct ospf_lsa *ospf_network_lsa_originate (struct ospf_interface *oi){ struct ospf_lsa *new; /* Create new network-LSA instance. */ new = ospf_network_lsa_new (oi); if (new == NULL) return NULL; /* Install LSA to LSDB. */ new = ospf_lsa_install (oi->ospf, oi, new); /* Update LSA origination count. */ oi->ospf->lsa_originate_count++; /* Flooding new LSA through area. */ ospf_flood_through_area (oi->area, NULL, new); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: Originate network-LSA %p", new->data->type, inet_ntoa (new->data->id), new); ospf_lsa_header_dump (new->data); } return new;}intospf_network_lsa_refresh (struct ospf_lsa *lsa, struct ospf_interface *oi)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -