📄 ospf_lsa.c
字号:
{ struct ospf_area *area = lsa->area; struct ospf_lsa *new; assert (lsa->data); /* Delete LSA from neighbor retransmit-list. */ ospf_ls_retransmit_delete_nbr_area (area, lsa); /* Create new network-LSA instance. */ new = ospf_network_lsa_new (oi); if (new == NULL) return -1; new->data->ls_seqnum = lsa_seqnum_increment (lsa); ospf_lsa_install (area->ospf, oi, new); /* Flood LSA through aera. */ ospf_flood_through_area (area, NULL, new); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: network-LSA refresh", new->data->type, inet_ntoa (new->data->id)); ospf_lsa_header_dump (new->data); } return 0;}intospf_network_lsa_refresh_timer (struct thread *t){ struct ospf_interface *oi; oi = THREAD_ARG (t); oi->t_network_lsa_self = NULL; if (oi->network_lsa_self) /* Now refresh network-LSA. */ ospf_network_lsa_refresh (oi->network_lsa_self, oi); else /* Newly create network-LSA. */ ospf_network_lsa_originate (oi); return 0;}voidospf_network_lsa_timer_add (struct ospf_interface *oi){ /* Keep interface's self-originated network-LSA. */ struct ospf_lsa *lsa = oi->network_lsa_self; /* Cancel previously schedules network-LSA timer. */ if (oi->t_network_lsa_self) if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type2]: Cancel previous network-LSA timer"); OSPF_TIMER_OFF (oi->t_network_lsa_self); /* If network-LSA is originated previously, check the interval time. */ if (lsa) { int delay; if ((delay = ospf_lsa_refresh_delay (lsa)) > 0) { oi->t_network_lsa_self = thread_add_timer (master, ospf_network_lsa_refresh_timer, oi, delay); return; } } if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("Scheduling network-LSA origination right away"); /* Immediately refresh network-LSA. */ oi->t_network_lsa_self = thread_add_event (master, ospf_network_lsa_refresh_timer, oi, 0);}voidstream_put_ospf_metric (struct stream *s, u_int32_t metric_value){ u_int32_t metric; char *mp; /* Put 0 metric. TOS metric is not supported. */ metric = htonl (metric_value); mp = (char *) &metric; mp++; stream_put (s, mp, 3);}/* summary-LSA related functions. */voidospf_summary_lsa_body_set (struct stream *s, struct prefix *p, u_int32_t metric){ struct in_addr mask; masklen2ip (p->prefixlen, &mask); /* Put Network Mask. */ stream_put_ipv4 (s, mask.s_addr); /* Set # TOS. */ stream_putc (s, (u_char) 0); /* Set metric. */ stream_put_ospf_metric (s, metric);}struct ospf_lsa *ospf_summary_lsa_new (struct ospf_area *area, struct prefix *p, u_int32_t metric, struct in_addr id){ struct stream *s; struct ospf_lsa *new; struct lsa_header *lsah; int length; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type3]: Create summary-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, LSA_OPTIONS_GET (area), OSPF_SUMMARY_LSA, id, area->ospf->router_id); /* Set summary-LSA body fields. */ ospf_summary_lsa_body_set (s, p, metric); /* Set length. */ length = stream_get_endp (s); lsah->length = htons (length); /* Create OSPF LSA instance. */ new = ospf_lsa_new (); new->area = 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 Summary-LSA. */struct ospf_lsa *ospf_summary_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, struct ospf_area *area){ struct ospf_lsa *new; struct in_addr id; id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_SUMMARY_LSA, p); /* Create new summary-LSA instance. */ new = ospf_summary_lsa_new (area, (struct prefix *) p, metric, id); /* Instlal 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 summary-LSA %p", new->data->type, inet_ntoa (new->data->id), new); ospf_lsa_header_dump (new->data); } return new;}struct ospf_lsa*ospf_summary_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa){ struct ospf_lsa *new; struct summary_lsa *sl; struct prefix p; /* Sanity check. */ assert (lsa->data); sl = (struct summary_lsa *)lsa->data; p.prefixlen = ip_masklen (sl->mask); new = ospf_summary_lsa_new (lsa->area, &p, GET_METRIC (sl->metric), sl->header.id); new->data->ls_seqnum = lsa_seqnum_increment (lsa); /* Re-calculate checksum. */ ospf_lsa_checksum (new->data); ospf_lsa_install (ospf, NULL, new); /* Flood LSA through AS. */ ospf_flood_through_area (new->area, NULL, new); /* Debug logging. */ if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: summary-LSA refresh", new->data->type, inet_ntoa (new->data->id)); ospf_lsa_header_dump (new->data); } return new;}/* summary-ASBR-LSA related functions. */voidospf_summary_asbr_lsa_body_set (struct stream *s, struct prefix *p, u_int32_t metric){ struct in_addr mask; masklen2ip (p->prefixlen, &mask); /* Put Network Mask. */ stream_put_ipv4 (s, mask.s_addr); /* Set # TOS. */ stream_putc (s, (u_char) 0); /* Set metric. */ stream_put_ospf_metric (s, metric);}struct ospf_lsa *ospf_summary_asbr_lsa_new (struct ospf_area *area, struct prefix *p, u_int32_t metric, struct in_addr id){ struct stream *s; struct ospf_lsa *new; struct lsa_header *lsah; int length; if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type3]: Create summary-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, LSA_OPTIONS_GET (area), OSPF_ASBR_SUMMARY_LSA, id, area->ospf->router_id); /* Set summary-LSA body fields. */ ospf_summary_asbr_lsa_body_set (s, p, metric); /* Set length. */ length = stream_get_endp (s); lsah->length = htons (length); /* Create OSPF LSA instance. */ new = ospf_lsa_new (); new->area = 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 summary-ASBR-LSA. */struct ospf_lsa *ospf_summary_asbr_lsa_originate (struct prefix_ipv4 *p, u_int32_t metric, struct ospf_area *area){ struct ospf_lsa *new; struct in_addr id; id = ospf_lsa_unique_id (area->ospf, area->lsdb, OSPF_ASBR_SUMMARY_LSA, p); /* Create new summary-LSA instance. */ new = ospf_summary_asbr_lsa_new (area, (struct prefix *) p, metric, id); /* 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 summary-ASBR-LSA %p", new->data->type, inet_ntoa (new->data->id), new); ospf_lsa_header_dump (new->data); } return new;}struct ospf_lsa*ospf_summary_asbr_lsa_refresh (struct ospf *ospf, struct ospf_lsa *lsa){ struct ospf_lsa *new; struct summary_lsa *sl; struct prefix p; /* Sanity check. */ assert (lsa->data); sl = (struct summary_lsa *)lsa->data; p.prefixlen = ip_masklen (sl->mask); new = ospf_summary_asbr_lsa_new (lsa->area, &p, GET_METRIC (sl->metric), sl->header.id); new->data->ls_seqnum = lsa_seqnum_increment (lsa); /* Re-calculate checksum. */ ospf_lsa_checksum (new->data); ospf_lsa_install (ospf, NULL, new); /* Flood LSA through area. */ ospf_flood_through_area (new->area, NULL, new); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { zlog_info ("LSA[Type%d:%s]: summary-ASBR-LSA refresh", new->data->type, inet_ntoa (new->data->id)); ospf_lsa_header_dump (new->data); } return new;}/* AS-external-LSA related functions. *//* Get nexthop for AS-external-LSAs. Return nexthop if its interface is connected, else 0*/struct in_addrospf_external_lsa_nexthop_get (struct ospf *ospf, struct in_addr nexthop){ struct in_addr fwd; struct prefix nh; listnode n1; fwd.s_addr = 0; if (!nexthop.s_addr) return fwd; /* Check whether nexthop is covered by OSPF network. */ nh.family = AF_INET; nh.u.prefix4 = nexthop; nh.prefixlen = IPV4_MAX_BITLEN; for (n1 = listhead (ospf->oiflist); n1; nextnode (n1)) { struct ospf_interface *oi = getdata (n1); if (if_is_up (oi->ifp)) if (oi->address->family == AF_INET) if (prefix_match (oi->address, &nh)) return nexthop; } return fwd;}#ifdef HAVE_NSSA/* NSSA-external-LSA related functions. *//* Get 1st IP connection for Forward Addr */ struct in_addrospf_get_ip_from_ifp (struct ospf_interface *oi){ struct in_addr fwd; fwd.s_addr = 0; if (if_is_up (oi->ifp)) return oi->address->u.prefix4; return fwd;}/* Get 1st IP connection for Forward Addr */struct in_addrospf_get_nssa_ip (struct ospf_area *area){ struct in_addr fwd; struct in_addr best_default; listnode n1; fwd.s_addr = 0; best_default.s_addr = 0; for (n1 = listhead (area->ospf->oiflist); n1; nextnode (n1)) { struct ospf_interface *oi = getdata (n1); if (if_is_up (oi->ifp)) if (oi->area->external_routing == OSPF_AREA_NSSA) if (oi->address && oi->address->family == AF_INET) { if (best_default.s_addr == 0) best_default = oi->address->u.prefix4; if (oi->area == area) return oi->address->u.prefix4; } } if (best_default.s_addr != 0) return best_default; return fwd;}#endif /* HAVE_NSSA */#define DEFAULT_DEFAULT_METRIC 20#define DEFAULT_DEFAULT_ORIGINATE_METRIC 10#define DEFAULT_DEFAULT_ALWAYS_METRIC 1#define DEFAULT_METRIC_TYPE EXTERNAL_METRIC_TYPE_2intmetric_type (struct ospf *ospf, u_char src){ return (ospf->dmetric[src].type < 0 ? DEFAULT_METRIC_TYPE : ospf->dmetric[src].type);}intmetric_value (struct ospf *ospf, u_char src){ if (ospf->dmetric[src].value < 0) { if (src == DEFAULT_ROUTE) { if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) return DEFAULT_DEFAULT_ORIGINATE_METRIC; else return DEFAULT_DEFAULT_ALWAYS_METRIC; } else if (ospf->default_metric < 0) return DEFAULT_DEFAULT_METRIC; else return ospf->default_metric; } return ospf->dmetric[src].value;}/* Set AS-external-LSA body. */voidospf_external_lsa_body_set (struct stream *s, struct external_info *ei, struct ospf *ospf){ struct prefix_ipv4 *p = &ei->p; struct in_addr mask, fwd_addr; u_int32_t mvalue; int mtype; int type; /* Put Network Mask. */ masklen2ip (p->prefixlen, &mask); stream_put_ipv4 (s, mask.s_addr); /* If prefix is default, specify DEFAULT_ROUTE. */ type = is_prefix_default (&ei->p) ? DEFAULT_ROUTE : ei->type; mtype = (ROUTEMAP_METRIC_TYPE (ei) != -1) ? ROUTEMAP_METRIC_TYPE (ei) : metric_type (ospf, type); mvalue = (ROUTEMAP_METRIC (ei) != -1) ? ROUTEMAP_METRIC (ei) : metric_value (ospf, type); /* Put type of external metric. */ stream_putc (s, (mtype == EXTERNAL_METRIC_TYPE_2 ? 0x80 : 0)); /* Put 0 metric. TOS metric is not supported. */ stream_put_ospf_metric (s, mvalue); /* Get forwarding address to nexthop if on the Connection List, else 0. */ fwd_addr = ospf_external_lsa_nexthop_get (ospf, ei->nexthop); /* Put forwarding address. */ stream_put_ipv4 (s, fwd_addr.s_addr); /* Put route tag -- This value should be introduced from configuration. */ stream_putl (s, 0);}/* Create new external-LSA. */struct ospf_lsa *ospf_external_lsa_new (struct ospf *ospf, struct external_info *ei, struct in_addr *old_id){ struct stream *s; struct lsa_header *lsah; struct ospf_lsa *new; struct in_addr id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -