📄 ospf_te.c
字号:
{ /* Note that TLV-length field is the size of array. */ lp->unrsv_bw.header.type = htons (TE_LINK_SUBTLV_UNRSV_BW); lp->unrsv_bw.header.length = htons (sizeof (lp->unrsv_bw.value)); htonf (fp, &lp->unrsv_bw.value [priority]); return;}static voidset_linkparams_rsc_clsclr (struct mpls_te_link *lp, u_int32_t classcolor){ lp->rsc_clsclr.header.type = htons (TE_LINK_SUBTLV_RSC_CLSCLR); lp->rsc_clsclr.header.length = htons (sizeof (lp->rsc_clsclr.value)); lp->rsc_clsclr.value = htonl (classcolor); return;}static voidinitialize_linkparams (struct mpls_te_link *lp){ struct interface *ifp = lp->ifp; struct ospf_interface *oi; float fval; int i; if ((oi = lookup_oi_by_ifp (ifp, NULL, OI_ANY)) == NULL) return; /* * Try to set initial values those can be derived from * zebra-interface information. */ set_linkparams_link_type (oi, lp); /* * Linux and *BSD kernel holds bandwidth parameter as an "int" type. * We may have to reconsider, if "ifp->bandwidth" type changes to float. */ fval = (float)((ifp->bandwidth ? ifp->bandwidth : OSPF_DEFAULT_BANDWIDTH) * 1000 / 8); set_linkparams_max_bw (lp, &fval); set_linkparams_max_rsv_bw (lp, &fval); for (i = 0; i < 8; i++) set_linkparams_unrsv_bw (lp, i, &fval); return;}static intis_mandated_params_set (struct mpls_te_link *lp){ int rc = 0; if (ntohs (OspfMplsTE.router_addr.header.type) == 0) goto out; if (ntohs (lp->link_type.header.type) == 0) goto out; if (ntohs (lp->link_id.header.type) == 0) goto out; rc = 1;out: return rc;}/*------------------------------------------------------------------------* * Followings are callback functions against generic Opaque-LSAs handling. *------------------------------------------------------------------------*/static intospf_mpls_te_new_if (struct interface *ifp){ struct mpls_te_link *new; int rc = -1; if (lookup_linkparams_by_ifp (ifp) != NULL) { zlog_warn ("ospf_mpls_te_new_if: ifp(%p) already in use?", ifp); rc = 0; /* Do nothing here. */ goto out; } if ((new = XMALLOC (MTYPE_OSPF_MPLS_TE_LINKPARAMS, sizeof (struct mpls_te_link))) == NULL) { zlog_warn ("ospf_mpls_te_new_if: XMALLOC: %s", strerror (errno)); goto out; } memset (new, 0, sizeof (struct mpls_te_link)); new->area = NULL; new->flags = 0; new->instance = get_mpls_te_instance_value (); new->ifp = ifp; initialize_linkparams (new); listnode_add (OspfMplsTE.iflist, new); /* Schedule Opaque-LSA refresh. *//* XXX */ rc = 0;out: return rc;}static intospf_mpls_te_del_if (struct interface *ifp){ struct mpls_te_link *lp; int rc = -1; if ((lp = lookup_linkparams_by_ifp (ifp)) != NULL) { list iflist = OspfMplsTE.iflist; /* Dequeue listnode entry from the list. */ listnode_delete (iflist, lp); /* Avoid misjudgement in the next lookup. */ if (listcount (iflist) == 0) iflist->head = iflist->tail = NULL; XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, lp); } /* Schedule Opaque-LSA refresh. *//* XXX */ rc = 0;/*out:*/ return rc;}static voidospf_mpls_te_ism_change (struct ospf_interface *oi, int old_state){ struct te_link_subtlv_link_type old_type; struct te_link_subtlv_link_id old_id; struct mpls_te_link *lp; if ((lp = lookup_linkparams_by_ifp (oi->ifp)) == NULL) { zlog_warn ("ospf_mpls_te_ism_change: Cannot get linkparams from OI(%s)?", IF_NAME (oi)); goto out; } if (oi->area == NULL || oi->area->ospf == NULL) { zlog_warn ("ospf_mpls_te_ism_change: Cannot refer to OSPF from OI(%s)?",IF_NAME (oi)); goto out; }#ifdef notyet if ((lp->area != NULL && ! IPV4_ADDR_SAME (&lp->area->area_id, &oi->area->area_id)) || (lp->area != NULL && oi->area == NULL)) { /* How should we consider this case? */ zlog_warn ("MPLS-TE: Area for OI(%s) has changed to [%s], flush previous LSAs", IF_NAME (oi), oi->area ? inet_ntoa (oi->area->area_id) : "N/A"); ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); }#endif /* Keep Area information in conbination with linkparams. */ lp->area = oi->area; switch (oi->state) { case ISM_PointToPoint: case ISM_DROther: case ISM_Backup: case ISM_DR: old_type = lp->link_type; old_id = lp->link_id; set_linkparams_link_type (oi, lp); set_linkparams_link_id (oi, lp); if ((ntohs (old_type.header.type) != ntohs (lp->link_type.header.type) || old_type.link_type.value != lp->link_type.link_type.value) || (ntohs (old_id.header.type) != ntohs (lp->link_id.header.type) || ntohl (old_id.value.s_addr) != ntohl (lp->link_id.value.s_addr))) { if (lp->flags & LPFLG_LSA_ENGAGED) ospf_mpls_te_lsa_schedule (lp, REFRESH_THIS_LSA); else ospf_mpls_te_lsa_schedule (lp, REORIGINATE_PER_AREA); } break; default: lp->link_type.header.type = htons (0); lp->link_id.header.type = htons (0); if (lp->flags & LPFLG_LSA_ENGAGED) ospf_mpls_te_lsa_schedule (lp, FLUSH_THIS_LSA); break; }out: return;}static voidospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_state){ /* So far, nothing to do here. */ return;}/*------------------------------------------------------------------------* * Followings are OSPF protocol processing functions for MPLS-TE. *------------------------------------------------------------------------*/static voidbuild_tlv_header (struct stream *s, struct te_tlv_header *tlvh){ stream_put (s, tlvh, sizeof (struct te_tlv_header)); return;}static voidbuild_router_tlv (struct stream *s){ struct te_tlv_header *tlvh = &OspfMplsTE.router_addr.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_link_type (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->link_type.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_link_id (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->link_id.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_lclif_ipaddr (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->lclif_ipaddr; if (tlvh != NULL && ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_rmtif_ipaddr (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr; if (tlvh != NULL && ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_te_metric (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->te_metric.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_max_bw (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->max_bw.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_max_rsv_bw (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->max_rsv_bw.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_unrsv_bw (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->unrsv_bw.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_subtlv_rsc_clsclr (struct stream *s, struct mpls_te_link *lp){ struct te_tlv_header *tlvh = &lp->rsc_clsclr.header; if (ntohs (tlvh->type) != 0) { build_tlv_header (s, tlvh); stream_put (s, tlvh+1, TLV_BODY_SIZE (tlvh)); } return;}static voidbuild_link_tlv (struct stream *s, struct mpls_te_link *lp){ set_linkparams_link_header (lp); build_tlv_header (s, &lp->link_header.header); build_link_subtlv_link_type (s, lp); build_link_subtlv_link_id (s, lp); build_link_subtlv_lclif_ipaddr (s, lp); build_link_subtlv_rmtif_ipaddr (s, lp); build_link_subtlv_te_metric (s, lp); build_link_subtlv_max_bw (s, lp); build_link_subtlv_max_rsv_bw (s, lp); build_link_subtlv_unrsv_bw (s, lp); build_link_subtlv_rsc_clsclr (s, lp); return;}static voidospf_mpls_te_lsa_body_set (struct stream *s, struct mpls_te_link *lp){ /* * The router address TLV is type 1, and ... * It must appear in exactly one * Traffic Engineering LSA originated by a router. */ build_router_tlv (s); /* * Only one Link TLV shall be carried in each LSA, allowing for fine * granularity changes in topology. */ build_link_tlv (s, lp); return;}/* Create new opaque-LSA. */static struct ospf_lsa *ospf_mpls_te_lsa_new (struct ospf_area *area, struct mpls_te_link *lp){ struct stream *s; struct lsa_header *lsah; struct ospf_lsa *new = NULL; u_char options, lsa_type; struct in_addr lsa_id; u_int32_t tmp; u_int16_t length; /* Create a stream for LSA. */ if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL) { zlog_warn ("ospf_mpls_te_lsa_new: stream_new() ?"); goto out; } lsah = (struct lsa_header *) STREAM_DATA (s); options = LSA_OPTIONS_GET (area);#ifdef HAVE_NSSA options |= LSA_NSSA_GET (area);#endif /* HAVE_NSSA */ options |= OSPF_OPTION_O; /* Don't forget this :-) */ lsa_type = OSPF_OPAQUE_AREA_LSA; tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, lp->instance); lsa_id.s_addr = htonl (tmp); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) zlog_info ("LSA[Type%d:%s]: Create an Opaque-LSA/MPLS-TE instance", lsa_type, inet_ntoa (lsa_id)); /* Set opaque-LSA header fields. */ lsa_header_set (s, options, lsa_type, lsa_id, area->ospf->router_id); /* Set opaque-LSA body fields. */ ospf_mpls_te_lsa_body_set (s, lp); /* Set length. */ length = stream_get_endp (s); lsah->length = htons (length); /* Now, create an OSPF LSA instance. */ if ((new = ospf_lsa_new ()) == NULL) { zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_new() ?"); stream_free (s); goto out; } if ((new->data = ospf_lsa_data_new (length)) == NULL) { zlog_warn ("ospf_mpls_te_lsa_new: ospf_lsa_data_new() ?"); ospf_lsa_free (new); new = NULL; stream_free (s); goto out; } new->area = area; SET_FLAG (new->flags, OSPF_LSA_SELF); memcpy (new->data, lsah, length); stream_free (s);out: return new;}static intospf_mpls_te_lsa_originate1 (struct ospf_area *area, struct mpls_te_link *lp){ struct ospf_lsa *new; int rc = -1; /* Create new Opaque-LSA/MPLS-TE instance. */ if ((new = ospf_mpls_te_lsa_new (area, lp)) == NULL) { zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_mpls_te_lsa_new() ?"); goto out; } /* Install this LSA into LSDB. */ if (ospf_lsa_install (area->ospf, NULL/*oi*/, new) == NULL) { zlog_warn ("ospf_mpls_te_lsa_originate1: ospf_lsa_install() ?"); ospf_lsa_free (new); goto out; } /* Now this linkparameter entry has associated LSA. */ lp->flags |= LPFLG_LSA_ENGAGED; /* Update new LSA origination count. */ area->ospf->lsa_originate_count++; /* Flood new LSA through area. */ ospf_flood_through_area (area, NULL/*nbr*/, new); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) { char area_id[INET_ADDRSTRLEN]; strcpy (area_id, inet_ntoa (area->area_id)); zlog_info ("LSA[Type%d:%s]: Originate Opaque-LSA/MPLS-TE: Area(%s), Link(%s)", new->data->type, inet_ntoa (new->data->id), area_id, lp->ifp->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -