📄 ospf_te.c
字号:
/* * This is an implementation of draft-katz-yeung-ospf-traffic-06.txt * Copyright (C) 2001 KDD R&D Laboratories, Inc. * http://www.kddlabs.co.jp/ * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. *//***** MTYPE definition is not reflected to "memory.h" yet. *****/#define MTYPE_OSPF_MPLS_TE_LINKPARAMS 0#include <zebra.h>#ifdef HAVE_OSPF_TE#ifndef HAVE_OPAQUE_LSA#error "Wrong configure option"#endif /* HAVE_OPAQUE_LSA */#include "linklist.h"#include "prefix.h"#include "if.h"#include "table.h"#include "memory.h"#include "command.h"#include "vty.h"#include "stream.h"#include "log.h"#include "thread.h"#include "hash.h"#include "sockunion.h" /* for inet_aton() */#include "ospfd/ospfd.h"#include "ospfd/ospf_interface.h"#include "ospfd/ospf_ism.h"#include "ospfd/ospf_asbr.h"#include "ospfd/ospf_lsa.h"#include "ospfd/ospf_lsdb.h"#include "ospfd/ospf_neighbor.h"#include "ospfd/ospf_nsm.h"#include "ospfd/ospf_flood.h"#include "ospfd/ospf_packet.h"#include "ospfd/ospf_spf.h"#include "ospfd/ospf_dump.h"#include "ospfd/ospf_route.h"#include "ospfd/ospf_ase.h"#include "ospfd/ospf_zebra.h"#include "ospfd/ospf_te.h"/* Following structure are internal use only. */struct ospf_mpls_te{ enum { disabled, enabled } status; /* List elements are zebra-interfaces (ifp), not ospf-interfaces (oi). */ list iflist; /* Store Router-TLV in network byte order. */ struct te_tlv_router_addr router_addr;};struct mpls_te_link{ /* * According to MPLS-TE (draft) specification, 24-bit Opaque-ID field * is subdivided into 8-bit "unused" field and 16-bit "instance" field. * In this implementation, each Link-TLV has its own instance. */ u_int32_t instance; /* Reference pointer to a Zebra-interface. */ struct interface *ifp; /* Area info in which this MPLS-TE link belongs to. */ struct ospf_area *area; /* Flags to manage this link parameters. */ u_int32_t flags;#define LPFLG_LOOKUP_DONE 0x1#define LPFLG_LSA_ENGAGED 0x2#define LPFLG_LSA_FORCED_REFRESH 0x4 /* Store Link-TLV in network byte order. */ struct te_tlv_link link_header; struct te_link_subtlv_link_type link_type; struct te_link_subtlv_link_id link_id; struct te_link_subtlv_lclif_ipaddr *lclif_ipaddr; struct te_link_subtlv_rmtif_ipaddr *rmtif_ipaddr; struct te_link_subtlv_te_metric te_metric; struct te_link_subtlv_max_bw max_bw; struct te_link_subtlv_max_rsv_bw max_rsv_bw; struct te_link_subtlv_unrsv_bw unrsv_bw; struct te_link_subtlv_rsc_clsclr rsc_clsclr;};/* * Global variable to manage Opaque-LSA/MPLS-TE on this node. * Note that all parameter values are stored in network byte order. */static struct ospf_mpls_te OspfMplsTE;enum oifstate { OI_ANY, OI_DOWN, OI_UP};enum sched_opcode { REORIGINATE_PER_AREA, REFRESH_THIS_LSA, FLUSH_THIS_LSA};/*------------------------------------------------------------------------* * Followings are initialize/terminate functions for MPLS-TE handling. *------------------------------------------------------------------------*/static int ospf_mpls_te_new_if (struct interface *ifp);static int ospf_mpls_te_del_if (struct interface *ifp);static void ospf_mpls_te_ism_change (struct ospf_interface *oi, int old_status);static void ospf_mpls_te_nsm_change (struct ospf_neighbor *nbr, int old_status);static void ospf_mpls_te_config_write_router (struct vty *vty);static void ospf_mpls_te_config_write_if (struct vty *vty, struct interface *ifp);static void ospf_mpls_te_show_info (struct vty *vty, struct ospf_lsa *lsa);static int ospf_mpls_te_lsa_originate (void *arg);static void ospf_mpls_te_lsa_refresh (struct ospf_lsa *lsa);static void ospf_mpls_te_lsa_schedule (struct mpls_te_link *lp, enum sched_opcode);static void del_mpls_te_link (void *val);static void ospf_mpls_te_register_vty (void);intospf_mpls_te_init (void){ int rc; rc = ospf_register_opaque_functab ( OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA, ospf_mpls_te_new_if, ospf_mpls_te_del_if, ospf_mpls_te_ism_change, ospf_mpls_te_nsm_change, ospf_mpls_te_config_write_router, ospf_mpls_te_config_write_if, NULL,/* ospf_mpls_te_config_write_debug */ ospf_mpls_te_show_info, ospf_mpls_te_lsa_originate, ospf_mpls_te_lsa_refresh, NULL,/* ospf_mpls_te_new_lsa_hook */ NULL /* ospf_mpls_te_del_lsa_hook */); if (rc != 0) { zlog_warn ("ospf_mpls_te_init: Failed to register functions"); goto out; } memset (&OspfMplsTE, 0, sizeof (struct ospf_mpls_te)); OspfMplsTE.status = disabled; OspfMplsTE.iflist = list_new (); OspfMplsTE.iflist->del = del_mpls_te_link; ospf_mpls_te_register_vty ();out: return rc;}voidospf_mpls_te_term (void){ list_delete (OspfMplsTE.iflist); OspfMplsTE.iflist = NULL; OspfMplsTE.status = disabled; ospf_delete_opaque_functab (OSPF_OPAQUE_AREA_LSA, OPAQUE_TYPE_TRAFFIC_ENGINEERING_LSA); return;}/*------------------------------------------------------------------------* * Followings are control functions for MPLS-TE parameters management. *------------------------------------------------------------------------*/static voiddel_mpls_te_link (void *val){ XFREE (MTYPE_OSPF_MPLS_TE_LINKPARAMS, val); return;}static u_int32_tget_mpls_te_instance_value (){ static u_int32_t seqno = 0; if (LEGAL_TE_INSTANCE_RANGE (seqno + 1)) seqno += 1; else seqno = 1; /* Avoid zero. */ return seqno;}static struct ospf_interface *lookup_oi_by_ifp (struct interface *ifp, struct ospf_area *area, enum oifstate oifstate){ struct ospf_interface *oi = NULL; struct route_node *rn; for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) { if ((oi = rn->info) == NULL) continue; switch (oifstate) { case OI_ANY: break; case OI_DOWN: if (ospf_if_is_enable (oi)) continue; break; case OI_UP: if (! ospf_if_is_enable (oi)) continue; break; default: zlog_warn ("lookup_oi_by_ifp: Unknown oifstate: %x", oifstate); goto out; } if (area == NULL || oi->area == area) return oi; }out: return NULL;}static struct mpls_te_link *lookup_linkparams_by_ifp (struct interface *ifp){ listnode node; struct mpls_te_link *lp; for (node = listhead (OspfMplsTE.iflist); node; nextnode (node)) if ((lp = getdata (node)) != NULL) if (lp->ifp == ifp) return lp; return NULL;}static struct mpls_te_link *lookup_linkparams_by_instance (struct ospf_lsa *lsa){ listnode node; struct mpls_te_link *lp; int key = GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)); for (node = listhead (OspfMplsTE.iflist); node; nextnode (node)) if ((lp = getdata (node)) != NULL) if (lp->instance == key) return lp; zlog_warn ("lookup_linkparams_by_instance: Entry not found: key(%x)", key); return NULL;}static voidospf_mpls_te_foreach_area ( void (*func)(struct mpls_te_link *lp, enum sched_opcode), enum sched_opcode sched_opcode){ listnode node, node2; struct mpls_te_link *lp; struct ospf_area *area; for (node = listhead (OspfMplsTE.iflist); node; nextnode (node)) { if ((lp = getdata (node)) == NULL) continue; if ((area = lp->area) == NULL) continue; if (lp->flags & LPFLG_LOOKUP_DONE) continue; if (func != NULL) (* func)(lp, sched_opcode); for (node2 = nextnode (node); node2; nextnode (node2)) if ((lp = getdata (node2)) != NULL) if (lp->area != NULL) if (IPV4_ADDR_SAME (&lp->area->area_id, &area->area_id)) lp->flags |= LPFLG_LOOKUP_DONE; } for (node = listhead (OspfMplsTE.iflist); node; nextnode (node)) if ((lp = getdata (node)) != NULL) if (lp->area != NULL) lp->flags &= ~LPFLG_LOOKUP_DONE; return;}static voidset_mpls_te_router_addr (struct in_addr ipv4){ OspfMplsTE.router_addr.header.type = htons (TE_TLV_ROUTER_ADDR); OspfMplsTE.router_addr.header.length = htons (sizeof (ipv4)); OspfMplsTE.router_addr.value = ipv4; return;}static voidset_linkparams_link_header (struct mpls_te_link *lp){ struct te_tlv_header *tlvh; u_int16_t length = 0; /* TE_LINK_SUBTLV_LINK_TYPE */ if (ntohs (lp->link_type.header.type) != 0) length += TLV_SIZE (&lp->link_type.header); /* TE_LINK_SUBTLV_LINK_ID */ if (ntohs (lp->link_id.header.type) != 0) length += TLV_SIZE (&lp->link_id.header); /* TE_LINK_SUBTLV_LCLIF_IPADDR */ if ((tlvh = (struct te_tlv_header *) lp->lclif_ipaddr) != NULL && ntohs (tlvh->type) != 0) length += TLV_SIZE (tlvh); /* TE_LINK_SUBTLV_RMTIF_IPADDR */ if ((tlvh = (struct te_tlv_header *) lp->rmtif_ipaddr) != NULL && ntohs (tlvh->type) != 0) length += TLV_SIZE (tlvh); /* TE_LINK_SUBTLV_TE_METRIC */ if (ntohs (lp->te_metric.header.type) != 0) length += TLV_SIZE (&lp->te_metric.header); /* TE_LINK_SUBTLV_MAX_BW */ if (ntohs (lp->max_bw.header.type) != 0) length += TLV_SIZE (&lp->max_bw.header); /* TE_LINK_SUBTLV_MAX_RSV_BW */ if (ntohs (lp->max_rsv_bw.header.type) != 0) length += TLV_SIZE (&lp->max_rsv_bw.header); /* TE_LINK_SUBTLV_UNRSV_BW */ if (ntohs (lp->unrsv_bw.header.type) != 0) length += TLV_SIZE (&lp->unrsv_bw.header); /* TE_LINK_SUBTLV_RSC_CLSCLR */ if (ntohs (lp->rsc_clsclr.header.type) != 0) length += TLV_SIZE (&lp->rsc_clsclr.header); lp->link_header.header.type = htons (TE_TLV_LINK); lp->link_header.header.length = htons (length); return;}static voidset_linkparams_link_type (struct ospf_interface *oi, struct mpls_te_link *lp){ lp->link_type.header.type = htons (TE_LINK_SUBTLV_LINK_TYPE); lp->link_type.header.length = htons (sizeof (lp->link_type.link_type.value)); switch (oi->type) { case OSPF_IFTYPE_POINTOPOINT: lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_PTP; break; case OSPF_IFTYPE_BROADCAST: case OSPF_IFTYPE_NBMA: lp->link_type.link_type.value = LINK_TYPE_SUBTLV_VALUE_MA; break; default: /* Not supported yet. *//* XXX */ lp->link_type.header.type = htons (0); break; } return;}static voidset_linkparams_link_id (struct ospf_interface *oi, struct mpls_te_link *lp){ struct ospf_neighbor *nbr; int done = 0; lp->link_id.header.type = htons (TE_LINK_SUBTLV_LINK_ID); lp->link_id.header.length = htons (sizeof (lp->link_id.value)); /* * The Link ID is identical to the contents of the Link ID field * in the Router LSA for these link types. */ switch (oi->type) { case OSPF_IFTYPE_POINTOPOINT: /* Take the router ID of the neighbor. */ if ((nbr = ospf_nbr_lookup_ptop (oi)) && nbr->state == NSM_Full) { lp->link_id.value = nbr->router_id; done = 1; } break; case OSPF_IFTYPE_BROADCAST: case OSPF_IFTYPE_NBMA: /* Take the interface address of the designated router. */ if ((nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &DR (oi))) == NULL) break; if (nbr->state == NSM_Full || (IPV4_ADDR_SAME (&oi->address->u.prefix4, &DR (oi)) && ospf_nbr_count (oi, NSM_Full) > 0)) { lp->link_id.value = DR (oi); done = 1; } break; default: /* Not supported yet. *//* XXX */ lp->link_id.header.type = htons (0); break; } if (! done) { struct in_addr mask; masklen2ip (oi->address->prefixlen, &mask); lp->link_id.value.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr; } return;}static voidset_linkparams_te_metric (struct mpls_te_link *lp, u_int32_t te_metric){ lp->te_metric.header.type = htons (TE_LINK_SUBTLV_TE_METRIC); lp->te_metric.header.length = htons (sizeof (lp->te_metric.value)); lp->te_metric.value = htonl (te_metric); return;}static voidset_linkparams_max_bw (struct mpls_te_link *lp, float *fp){ lp->max_bw.header.type = htons (TE_LINK_SUBTLV_MAX_BW); lp->max_bw.header.length = htons (sizeof (lp->max_bw.value)); htonf (fp, &lp->max_bw.value); return;}static voidset_linkparams_max_rsv_bw (struct mpls_te_link *lp, float *fp){ lp->max_rsv_bw.header.type = htons (TE_LINK_SUBTLV_MAX_RSV_BW); lp->max_rsv_bw.header.length = htons (sizeof (lp->max_rsv_bw.value)); htonf (fp, &lp->max_rsv_bw.value); return;}static voidset_linkparams_unrsv_bw (struct mpls_te_link *lp, int priority, float *fp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -