ospf_ri.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637
  1. /*
  2. * This is an implementation of RFC4970 Router Information
  3. * with support of RFC5088 PCE Capabilites announcement
  4. *
  5. * Module name: Router Information
  6. * Version: 0.99.22
  7. * Created: 2012-02-01 by Olivier Dugeon
  8. * Copyright (C) 2012 Orange Labs http://www.orange.com/
  9. *
  10. * This file is part of GNU Quagga.
  11. *
  12. * GNU Zebra is free software; you can redistribute it and/or modify it
  13. * under the terms of the GNU General Public License as published by the
  14. * Free Software Foundation; either version 2, or (at your option) any
  15. * later version.
  16. *
  17. * GNU Quagga is distributed in the hope that it will be useful, but
  18. * WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with GNU Quagga; see the file COPYING. If not, write to the Free
  24. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  25. * 02111-1307, USA.
  26. */
  27. #include <zebra.h>
  28. #include <math.h>
  29. #include "linklist.h"
  30. #include "prefix.h"
  31. #include "if.h"
  32. #include "table.h"
  33. #include "memory.h"
  34. #include "command.h"
  35. #include "vty.h"
  36. #include "stream.h"
  37. #include "log.h"
  38. #include "thread.h"
  39. #include "hash.h"
  40. #include "sockunion.h" /* for inet_aton() */
  41. #include "ospfd/ospfd.h"
  42. #include "ospfd/ospf_interface.h"
  43. #include "ospfd/ospf_ism.h"
  44. #include "ospfd/ospf_asbr.h"
  45. #include "ospfd/ospf_lsa.h"
  46. #include "ospfd/ospf_lsdb.h"
  47. #include "ospfd/ospf_neighbor.h"
  48. #include "ospfd/ospf_nsm.h"
  49. #include "ospfd/ospf_flood.h"
  50. #include "ospfd/ospf_packet.h"
  51. #include "ospfd/ospf_spf.h"
  52. #include "ospfd/ospf_dump.h"
  53. #include "ospfd/ospf_route.h"
  54. #include "ospfd/ospf_ase.h"
  55. #include "ospfd/ospf_zebra.h"
  56. #include "ospfd/ospf_ri.h"
  57. #include "ospfd/ospf_te.h"
  58. struct ospf_pce_info
  59. {
  60. /* Store Router Information PCE TLV and SubTLV in network byte order. */
  61. struct ri_tlv_pce pce_header;
  62. struct ri_pce_subtlv_address pce_address;
  63. struct ri_pce_subtlv_path_scope pce_scope;
  64. struct list *pce_domain;
  65. struct list *pce_neighbor;
  66. struct ri_pce_subtlv_cap_flag pce_cap_flag;
  67. };
  68. /* Following structure are internal use only. */
  69. struct ospf_router_info
  70. {
  71. status_t status;
  72. u_int8_t registered;
  73. u_int8_t scope;
  74. /* Flags to manage this router information. */
  75. #define RIFLG_LOOKUP_DONE 0x1
  76. #define RIFLG_LSA_ENGAGED 0x2
  77. #define RIFLG_LSA_FORCED_REFRESH 0x4
  78. u_int32_t flags;
  79. /* area pointer if flooding is Type 10 Null if flooding is AS scope */
  80. struct ospf_area *area;
  81. struct in_addr area_id;
  82. /* Store Router Information Capabilities LSA */
  83. struct ri_tlv_router_cap router_cap;
  84. /* Store PCE capability LSA */
  85. struct ospf_pce_info pce_info;
  86. };
  87. /*
  88. * Global variable to manage Opaque-LSA/Router Information on this node.
  89. * Note that all parameter values are stored in network byte order.
  90. */
  91. static struct ospf_router_info OspfRI;
  92. /*------------------------------------------------------------------------------*
  93. * Followings are initialize/terminate functions for Router Information handling.
  94. *------------------------------------------------------------------------------*/
  95. static void ospf_router_info_ism_change (struct ospf_interface *oi,
  96. int old_status);
  97. static void ospf_router_info_nsm_change (struct ospf_neighbor *nbr,
  98. int old_status);
  99. static void ospf_router_info_config_write_router (struct vty *vty);
  100. static void ospf_router_info_show_info (struct vty *vty,
  101. struct ospf_lsa *lsa);
  102. static int ospf_router_info_lsa_originate (void *arg);
  103. static struct ospf_lsa *ospf_router_info_lsa_refresh (struct ospf_lsa *lsa);
  104. static void ospf_router_info_lsa_schedule (opcode_t opcode);
  105. static void ospf_router_info_register_vty (void);
  106. static void del_pce_info (void *val);
  107. int
  108. ospf_router_info_init (void)
  109. {
  110. memset (&OspfRI, 0, sizeof (struct ospf_router_info));
  111. OspfRI.status = disabled;
  112. OspfRI.registered = 0;
  113. OspfRI.scope = OSPF_OPAQUE_AS_LSA;
  114. OspfRI.flags = 0;
  115. /* Initialize pce domain and neighbor list */
  116. OspfRI.pce_info.pce_domain = list_new ();
  117. OspfRI.pce_info.pce_domain->del = del_pce_info;
  118. OspfRI.pce_info.pce_neighbor = list_new ();
  119. OspfRI.pce_info.pce_neighbor->del = del_pce_info;
  120. ospf_router_info_register_vty ();
  121. return 0;
  122. }
  123. static int
  124. ospf_router_info_register (u_int8_t scope)
  125. {
  126. int rc = 0;
  127. if (OspfRI.registered)
  128. return 0;
  129. zlog_info ("Register Router Information with scope %s(%d)",
  130. scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS", scope);
  131. rc = ospf_register_opaque_functab (scope,
  132. OPAQUE_TYPE_ROUTER_INFORMATION_LSA,
  133. NULL, /* new interface */
  134. NULL, /* del interface */
  135. ospf_router_info_ism_change,
  136. ospf_router_info_nsm_change,
  137. ospf_router_info_config_write_router,
  138. NULL, /* Config. write interface */
  139. NULL, /* Config. write debug */
  140. ospf_router_info_show_info,
  141. ospf_router_info_lsa_originate,
  142. ospf_router_info_lsa_refresh,
  143. NULL, /* new_lsa_hook */
  144. NULL); /* del_lsa_hook */
  145. if (rc != 0)
  146. {
  147. zlog_warn ("ospf_router_info_init: Failed to register functions");
  148. return rc;
  149. }
  150. OspfRI.registered = 1;
  151. OspfRI.scope = scope;
  152. return 0;
  153. }
  154. static int
  155. ospf_router_info_unregister ()
  156. {
  157. if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
  158. && (OspfRI.scope != OSPF_OPAQUE_AREA_LSA))
  159. {
  160. zlog_warn ("Unable to unregister Router Info functions: Wrong scope!");
  161. return -1;
  162. }
  163. ospf_delete_opaque_functab (OspfRI.scope,
  164. OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
  165. OspfRI.registered = 0;
  166. return 0;
  167. }
  168. void
  169. ospf_router_info_term (void)
  170. {
  171. list_delete (OspfRI.pce_info.pce_domain);
  172. list_delete (OspfRI.pce_info.pce_neighbor);
  173. OspfRI.pce_info.pce_domain = NULL;
  174. OspfRI.pce_info.pce_neighbor = NULL;
  175. OspfRI.status = disabled;
  176. ospf_router_info_unregister (OspfRI.scope);
  177. return;
  178. }
  179. static void
  180. del_pce_info (void *val)
  181. {
  182. XFREE (MTYPE_OSPF_PCE_PARAMS, val);
  183. return;
  184. }
  185. /*------------------------------------------------------------------------*
  186. * Followings are control functions for ROUTER INFORMATION parameters management.
  187. *------------------------------------------------------------------------*/
  188. static void
  189. set_router_info_capabilities (struct ri_tlv_router_cap *ric, u_int32_t cap)
  190. {
  191. ric->header.type = htons (RI_TLV_CAPABILITIES);
  192. ric->header.length = htons (RI_TLV_LENGTH);
  193. ric->value = htonl (cap);
  194. return;
  195. }
  196. static int
  197. set_pce_header (struct ospf_pce_info *pce)
  198. {
  199. u_int16_t length = 0;
  200. struct listnode *node;
  201. struct ri_pce_subtlv_domain *domain;
  202. struct ri_pce_subtlv_neighbor *neighbor;
  203. /* PCE Address */
  204. if (ntohs (pce->pce_address.header.type) != 0)
  205. length += RI_TLV_SIZE (&pce->pce_address.header);
  206. /* PCE Path Scope */
  207. if (ntohs (pce->pce_scope.header.type) != 0)
  208. length += RI_TLV_SIZE (&pce->pce_scope.header);
  209. /* PCE Domain */
  210. for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
  211. {
  212. if (ntohs (domain->header.type) != 0)
  213. length += RI_TLV_SIZE (&domain->header);
  214. }
  215. /* PCE Neighbor */
  216. for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
  217. {
  218. if (ntohs (neighbor->header.type) != 0)
  219. length += RI_TLV_SIZE (&neighbor->header);
  220. }
  221. /* PCE Capabilities */
  222. if (ntohs (pce->pce_cap_flag.header.type) != 0)
  223. length += RI_TLV_SIZE (&pce->pce_cap_flag.header);
  224. if (length != 0)
  225. {
  226. pce->pce_header.header.type = htons (RI_TLV_PCE);
  227. pce->pce_header.header.length = htons (length);
  228. }
  229. else
  230. {
  231. pce->pce_header.header.type = 0;
  232. pce->pce_header.header.length = 0;
  233. }
  234. return length;
  235. }
  236. static void
  237. set_pce_address (struct in_addr ipv4, struct ospf_pce_info *pce)
  238. {
  239. /* Enable PCE Info */
  240. pce->pce_header.header.type = htons (RI_TLV_PCE);
  241. /* Set PCE Address */
  242. pce->pce_address.header.type = htons (RI_PCE_SUBTLV_ADDRESS);
  243. pce->pce_address.header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
  244. pce->pce_address.address.type = htons (PCE_ADDRESS_TYPE_IPV4);
  245. pce->pce_address.address.value = ipv4;
  246. return;
  247. }
  248. static void
  249. set_pce_path_scope (u_int32_t scope, struct ospf_pce_info *pce)
  250. {
  251. /* Enable PCE Info */
  252. pce->pce_header.header.type = htons (RI_TLV_PCE);
  253. /* Set PCE Scope */
  254. pce->pce_scope.header.type = htons (RI_PCE_SUBTLV_PATH_SCOPE);
  255. pce->pce_scope.header.length = htons (RI_TLV_LENGTH);
  256. pce->pce_scope.value = htonl (scope);
  257. return;
  258. }
  259. static void
  260. set_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
  261. {
  262. struct ri_pce_subtlv_domain *new;
  263. /* Enable PCE Info */
  264. pce->pce_header.header.type = htons (RI_TLV_PCE);
  265. /* Create new domain info */
  266. new =
  267. XCALLOC (MTYPE_OSPF_PCE_PARAMS,
  268. sizeof (struct ri_pce_subtlv_domain));
  269. new->header.type = htons (RI_PCE_SUBTLV_DOMAIN);
  270. new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
  271. new->type = htons (type);
  272. new->value = htonl (domain);
  273. /* Add new domain to the list */
  274. listnode_add (pce->pce_domain, new);
  275. return;
  276. }
  277. static void
  278. unset_pce_domain (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
  279. {
  280. struct listnode *node;
  281. struct ri_pce_subtlv_domain *old = NULL;
  282. int found = 0;
  283. /* Search the corresponding node */
  284. for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, old))
  285. {
  286. if ((old->type == htons (type)) && (old->value == htonl (domain)))
  287. {
  288. found = 1;
  289. break;
  290. }
  291. }
  292. /* if found remove it */
  293. if (found)
  294. {
  295. listnode_delete (pce->pce_domain, old);
  296. /* Avoid misjudgement in the next lookup. */
  297. if (listcount (pce->pce_domain) == 0)
  298. pce->pce_domain->head = pce->pce_domain->tail = NULL;
  299. /* Finally free the old domain */
  300. XFREE (MTYPE_OSPF_PCE_PARAMS, old);
  301. }
  302. }
  303. static void
  304. set_pce_neighbor (u_int16_t type, u_int32_t domain, struct ospf_pce_info *pce)
  305. {
  306. struct ri_pce_subtlv_neighbor *new;
  307. /* Enable PCE Info */
  308. pce->pce_header.header.type = htons (RI_TLV_PCE);
  309. /* Create new neighbor info */
  310. new =
  311. XCALLOC (MTYPE_OSPF_PCE_PARAMS,
  312. sizeof (struct ri_pce_subtlv_neighbor));
  313. new->header.type = htons (RI_PCE_SUBTLV_NEIGHBOR);
  314. new->header.length = htons (PCE_ADDRESS_LENGTH_IPV4);
  315. new->type = htons (type);
  316. new->value = htonl (domain);
  317. /* Add new domain to the list */
  318. listnode_add (pce->pce_neighbor, new);
  319. return;
  320. }
  321. static void
  322. unset_pce_neighbor (u_int16_t type, u_int32_t domain,
  323. struct ospf_pce_info *pce)
  324. {
  325. struct listnode *node;
  326. struct ri_pce_subtlv_neighbor *old = NULL;
  327. int found = 0;
  328. /* Search the corresponding node */
  329. for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, old))
  330. {
  331. if ((old->type == htons (type)) && (old->value == htonl (domain)))
  332. {
  333. found = 1;
  334. break;
  335. }
  336. }
  337. /* if found remove it */
  338. if (found)
  339. {
  340. listnode_delete (pce->pce_neighbor, old);
  341. /* Avoid misjudgement in the next lookup. */
  342. if (listcount (pce->pce_neighbor) == 0)
  343. pce->pce_neighbor->head = pce->pce_neighbor->tail = NULL;
  344. /* Finally free the old domain */
  345. XFREE (MTYPE_OSPF_PCE_PARAMS, old);
  346. }
  347. }
  348. static void
  349. set_pce_cap_flag (u_int32_t cap, struct ospf_pce_info *pce)
  350. {
  351. /* Enable PCE Info */
  352. pce->pce_header.header.type = htons (RI_TLV_PCE);
  353. /* Set PCE Capabilities flag */
  354. pce->pce_cap_flag.header.type = htons (RI_PCE_SUBTLV_CAP_FLAG);
  355. pce->pce_cap_flag.header.length = htons (RI_TLV_LENGTH);
  356. pce->pce_cap_flag.value = htonl (cap);
  357. return;
  358. }
  359. static void
  360. unset_param (struct ri_tlv_header *tlv)
  361. {
  362. tlv->type = 0;
  363. /* Fill the Value to 0 */
  364. memset ((tlv + RI_TLV_HDR_SIZE), 0, RI_TLV_BODY_SIZE (tlv));
  365. tlv->length = 0;
  366. return;
  367. }
  368. static void
  369. initialize_params (struct ospf_router_info *ori)
  370. {
  371. u_int32_t cap;
  372. struct ospf *top;
  373. /*
  374. * Initialize default Router Information Capabilities.
  375. */
  376. cap = 0;
  377. cap = cap | RI_TE_SUPPORT;
  378. set_router_info_capabilities (&ori->router_cap, cap);
  379. /* If Area address is not null and exist, retrieve corresponding structure */
  380. top = ospf_lookup ();
  381. zlog_info ("RI-> Initialize Router Info for %s scope within area %s",
  382. OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS",
  383. inet_ntoa (OspfRI.area_id));
  384. /* Try to get the Area context at this step. Do it latter if not available */
  385. if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
  386. OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id);
  387. /*
  388. * Initialize default PCE Information values
  389. */
  390. /* PCE address == OSPF Router ID */
  391. set_pce_address (top->router_id, &ori->pce_info);
  392. /* PCE scope */
  393. cap = 7; /* Set L, R and Rd bits to one = intra & inter-area path computation */
  394. set_pce_path_scope (cap, &ori->pce_info);
  395. /* PCE Capabilities */
  396. cap =
  397. PCE_CAP_BIDIRECTIONAL | PCE_CAP_DIVERSE_PATH | PCE_CAP_OBJECTIVES |
  398. PCE_CAP_ADDITIVE | PCE_CAP_MULTIPLE_REQ;
  399. set_pce_cap_flag (cap, &ori->pce_info);
  400. /* Finally compute PCE header */
  401. set_pce_header (&ori->pce_info);
  402. return;
  403. }
  404. static int
  405. is_mandated_params_set (struct ospf_router_info ori)
  406. {
  407. int rc = 0;
  408. if (ntohs (ori.router_cap.header.type) == 0)
  409. goto out;
  410. if ((ntohs (ori.pce_info.pce_header.header.type) == RI_TLV_PCE)
  411. && (ntohs (ori.pce_info.pce_address.header.type) == 0)
  412. && (ntohs (ori.pce_info.pce_cap_flag.header.type) == 0))
  413. goto out;
  414. rc = 1;
  415. out:
  416. return rc;
  417. }
  418. /*------------------------------------------------------------------------*
  419. * Followings are callback functions against generic Opaque-LSAs handling.
  420. *------------------------------------------------------------------------*/
  421. static void
  422. ospf_router_info_ism_change (struct ospf_interface *oi, int old_state)
  423. {
  424. /* So far, nothing to do here. */
  425. return;
  426. }
  427. static void
  428. ospf_router_info_nsm_change (struct ospf_neighbor *nbr, int old_state)
  429. {
  430. /* So far, nothing to do here. */
  431. return;
  432. }
  433. /*------------------------------------------------------------------------*
  434. * Followings are OSPF protocol processing functions for ROUTER INFORMATION
  435. *------------------------------------------------------------------------*/
  436. static void
  437. build_tlv_header (struct stream *s, struct ri_tlv_header *tlvh)
  438. {
  439. stream_put (s, tlvh, sizeof (struct ri_tlv_header));
  440. return;
  441. }
  442. static void
  443. build_tlv (struct stream *s, struct ri_tlv_header *tlvh)
  444. {
  445. if (ntohs (tlvh->type) != 0)
  446. {
  447. build_tlv_header (s, tlvh);
  448. stream_put (s, tlvh + 1, RI_TLV_BODY_SIZE (tlvh));
  449. }
  450. return;
  451. }
  452. static void
  453. ospf_router_info_lsa_body_set (struct stream *s)
  454. {
  455. struct listnode *node;
  456. struct ri_pce_subtlv_domain *domain;
  457. struct ri_pce_subtlv_neighbor *neighbor;
  458. /* Build Router Information TLV */
  459. build_tlv (s, &OspfRI.router_cap.header);
  460. /* Add RI PCE TLV if it is set */
  461. /* Compute PCE Info header first */
  462. if ((set_pce_header (&OspfRI.pce_info)) != 0)
  463. {
  464. /* Build PCE TLV */
  465. build_tlv_header (s, &OspfRI.pce_info.pce_header.header);
  466. /* Build PCE address sub-tlv */
  467. build_tlv (s, &OspfRI.pce_info.pce_address.header);
  468. /* Build PCE path scope sub-tlv */
  469. build_tlv (s, &OspfRI.pce_info.pce_scope.header);
  470. /* Build PCE domain sub-tlv */
  471. for (ALL_LIST_ELEMENTS_RO (OspfRI.pce_info.pce_domain, node, domain))
  472. build_tlv (s, &domain->header);
  473. /* Build PCE neighbor sub-tlv */
  474. for (ALL_LIST_ELEMENTS_RO
  475. (OspfRI.pce_info.pce_neighbor, node, neighbor))
  476. build_tlv (s, &neighbor->header);
  477. /* Build PCE cap flag sub-tlv */
  478. build_tlv (s, &OspfRI.pce_info.pce_cap_flag.header);
  479. }
  480. return;
  481. }
  482. /* Create new opaque-LSA. */
  483. static struct ospf_lsa *
  484. ospf_router_info_lsa_new ()
  485. {
  486. struct ospf *top;
  487. struct stream *s;
  488. struct lsa_header *lsah;
  489. struct ospf_lsa *new = NULL;
  490. u_char options, lsa_type;
  491. struct in_addr lsa_id;
  492. u_int32_t tmp;
  493. u_int16_t length;
  494. /* Create a stream for LSA. */
  495. if ((s = stream_new (OSPF_MAX_LSA_SIZE)) == NULL)
  496. {
  497. zlog_warn ("ospf_router_info_lsa_new: stream_new() ?");
  498. goto out;
  499. }
  500. lsah = (struct lsa_header *) STREAM_DATA (s);
  501. options = OSPF_OPTION_E; /* Enable AS external as we flood RI with Opaque Type 11 */
  502. options |= OSPF_OPTION_O; /* Don't forget this :-) */
  503. lsa_type = OspfRI.scope;
  504. /* LSA ID == 0 for Router Information see RFC 4970 */
  505. tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
  506. lsa_id.s_addr = htonl (tmp);
  507. if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
  508. zlog_debug
  509. ("LSA[Type%d:%s]: Create an Opaque-LSA/ROUTER INFORMATION instance",
  510. lsa_type, inet_ntoa (lsa_id));
  511. top = ospf_lookup ();
  512. /* Set opaque-LSA header fields. */
  513. lsa_header_set (s, options, lsa_type, lsa_id, top->router_id);
  514. /* Set opaque-LSA body fields. */
  515. ospf_router_info_lsa_body_set (s);
  516. /* Set length. */
  517. length = stream_get_endp (s);
  518. lsah->length = htons (length);
  519. /* Now, create an OSPF LSA instance. */
  520. if ((new = ospf_lsa_new ()) == NULL)
  521. {
  522. zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_new() ?");
  523. stream_free (s);
  524. goto out;
  525. }
  526. if ((new->data = ospf_lsa_data_new (length)) == NULL)
  527. {
  528. zlog_warn ("ospf_router_info_lsa_new: ospf_lsa_data_new() ?");
  529. ospf_lsa_unlock (&new);
  530. new = NULL;
  531. stream_free (s);
  532. goto out;
  533. }
  534. new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */
  535. SET_FLAG (new->flags, OSPF_LSA_SELF);
  536. memcpy (new->data, lsah, length);
  537. stream_free (s);
  538. out:return new;
  539. }
  540. static int
  541. ospf_router_info_lsa_originate1 (void *arg)
  542. {
  543. struct ospf_lsa *new;
  544. struct ospf *top;
  545. struct ospf_area *area;
  546. int rc = -1;
  547. /* First check if the area is known if flooding scope is Area */
  548. if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
  549. {
  550. area = (struct ospf_area *) arg;
  551. if (area->area_id.s_addr != OspfRI.area_id.s_addr)
  552. {
  553. zlog_debug
  554. ("RI -> This is not the Router Information Area. Stop processing");
  555. goto out;
  556. }
  557. OspfRI.area = area;
  558. }
  559. /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
  560. if ((new = ospf_router_info_lsa_new ()) == NULL)
  561. {
  562. zlog_warn
  563. ("ospf_router_info_lsa_originate1: ospf_router_info_lsa_new() ?");
  564. goto out;
  565. }
  566. /* Get ospf info */
  567. top = ospf_lookup ();
  568. /* Install this LSA into LSDB. */
  569. if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
  570. {
  571. zlog_warn ("ospf_router_info_lsa_originate1: ospf_lsa_install() ?");
  572. ospf_lsa_unlock (&new);
  573. goto out;
  574. }
  575. /* Now this Router Info parameter entry has associated LSA. */
  576. SET_FLAG (OspfRI.flags, RIFLG_LSA_ENGAGED);
  577. /* Update new LSA origination count. */
  578. top->lsa_originate_count++;
  579. /* Flood new LSA through AS. */
  580. if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
  581. ospf_flood_through_as (top, NULL /*nbr */ , new);
  582. else
  583. ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new);
  584. if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
  585. {
  586. zlog_debug ("LSA[Type%d:%s]: Originate Opaque-LSA/ROUTER INFORMATION",
  587. new->data->type, inet_ntoa (new->data->id));
  588. ospf_lsa_header_dump (new->data);
  589. }
  590. rc = 0;
  591. out:return rc;
  592. }
  593. static int
  594. ospf_router_info_lsa_originate (void *arg)
  595. {
  596. int rc = -1;
  597. if (OspfRI.status == disabled)
  598. {
  599. zlog_info
  600. ("ospf_router_info_lsa_originate: ROUTER INFORMATION is disabled now.");
  601. rc = 0; /* This is not an error case. */
  602. goto out;
  603. }
  604. /* Check if Router Information LSA is already engaged */
  605. if (OspfRI.flags & RIFLG_LSA_ENGAGED)
  606. {
  607. if (OspfRI.flags & RIFLG_LSA_FORCED_REFRESH)
  608. {
  609. OspfRI.flags &= ~RIFLG_LSA_FORCED_REFRESH;
  610. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  611. }
  612. }
  613. else
  614. {
  615. if (!is_mandated_params_set (OspfRI))
  616. zlog_warn
  617. ("ospf_router_info_lsa_originate: lacks mandated ROUTER INFORMATION parameters");
  618. /* Ok, let's try to originate an LSA */
  619. if (ospf_router_info_lsa_originate1 (arg) != 0)
  620. goto out;
  621. }
  622. rc = 0;
  623. out:return rc;
  624. }
  625. static struct ospf_lsa *
  626. ospf_router_info_lsa_refresh (struct ospf_lsa *lsa)
  627. {
  628. struct ospf_lsa *new = NULL;
  629. struct ospf *top;
  630. if (OspfRI.status == disabled)
  631. {
  632. /*
  633. * This LSA must have flushed before due to ROUTER INFORMATION status change.
  634. * It seems a slip among routers in the routing domain.
  635. */
  636. zlog_info
  637. ("ospf_router_info_lsa_refresh: ROUTER INFORMATION is disabled now.");
  638. lsa->data->ls_age = htons (OSPF_LSA_MAXAGE); /* Flush it anyway. */
  639. }
  640. /* Verify that the Router Information ID is supported */
  641. if (GET_OPAQUE_ID (ntohl (lsa->data->id.s_addr)) != 0)
  642. {
  643. zlog_warn
  644. ("ospf_router_info_lsa_refresh: Unsupported Router Information ID");
  645. goto out;
  646. }
  647. /* If the lsa's age reached to MaxAge, start flushing procedure. */
  648. if (IS_LSA_MAXAGE (lsa))
  649. {
  650. OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
  651. ospf_opaque_lsa_flush_schedule (lsa);
  652. goto out;
  653. }
  654. /* Create new Opaque-LSA/ROUTER INFORMATION instance. */
  655. if ((new = ospf_router_info_lsa_new ()) == NULL)
  656. {
  657. zlog_warn
  658. ("ospf_router_info_lsa_refresh: ospf_router_info_lsa_new() ?");
  659. goto out;
  660. }
  661. new->data->ls_seqnum = lsa_seqnum_increment (lsa);
  662. /* Install this LSA into LSDB. */
  663. /* Given "lsa" will be freed in the next function. */
  664. top = ospf_lookup ();
  665. if (ospf_lsa_install (top, NULL /*oi */ , new) == NULL)
  666. {
  667. zlog_warn ("ospf_router_info_lsa_refresh: ospf_lsa_install() ?");
  668. ospf_lsa_unlock (&new);
  669. goto out;
  670. }
  671. /* Flood updated LSA through AS or AREA depending of OspfRI.scope. */
  672. if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
  673. ospf_flood_through_as (top, NULL /*nbr */ , new);
  674. else
  675. ospf_flood_through_area (OspfRI.area, NULL /*nbr */ , new);
  676. /* Debug logging. */
  677. if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
  678. {
  679. zlog_debug ("LSA[Type%d:%s]: Refresh Opaque-LSA/ROUTER INFORMATION",
  680. new->data->type, inet_ntoa (new->data->id));
  681. ospf_lsa_header_dump (new->data);
  682. }
  683. out:return new;
  684. }
  685. static void
  686. ospf_router_info_lsa_schedule (opcode_t opcode)
  687. {
  688. struct ospf_lsa lsa;
  689. struct lsa_header lsah;
  690. struct ospf *top;
  691. u_int32_t tmp;
  692. memset (&lsa, 0, sizeof (lsa));
  693. memset (&lsah, 0, sizeof (lsah));
  694. zlog_debug ("RI-> LSA schedule %s%s%s",
  695. opcode == REORIGINATE_THIS_LSA ? "Re-Originate" : "",
  696. opcode == REFRESH_THIS_LSA ? "Refresh" : "",
  697. opcode == FLUSH_THIS_LSA ? "Flush" : "");
  698. top = ospf_lookup ();
  699. if ((OspfRI.scope == OSPF_OPAQUE_AREA_LSA) && (OspfRI.area == NULL))
  700. {
  701. zlog_warn
  702. ("ospf_router_info_lsa_schedule(): Router Info is Area scope flooding but area is not set");
  703. OspfRI.area = ospf_area_lookup_by_area_id (top, OspfRI.area_id);
  704. }
  705. lsa.area = OspfRI.area;
  706. lsa.data = &lsah;
  707. lsah.type = OspfRI.scope;
  708. /* LSA ID is set to 0 for the Router Information. See RFC 4970 */
  709. tmp = SET_OPAQUE_LSID (OPAQUE_TYPE_ROUTER_INFORMATION_LSA, 0);
  710. lsah.id.s_addr = htonl (tmp);
  711. switch (opcode)
  712. {
  713. case REORIGINATE_THIS_LSA:
  714. if (OspfRI.scope == OSPF_OPAQUE_AREA_LSA)
  715. ospf_opaque_lsa_reoriginate_schedule ((void *) OspfRI.area,
  716. OSPF_OPAQUE_AREA_LSA,
  717. OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
  718. else
  719. ospf_opaque_lsa_reoriginate_schedule ((void *) top,
  720. OSPF_OPAQUE_AS_LSA,
  721. OPAQUE_TYPE_ROUTER_INFORMATION_LSA);
  722. break;
  723. case REFRESH_THIS_LSA:
  724. ospf_opaque_lsa_refresh_schedule (&lsa);
  725. break;
  726. case FLUSH_THIS_LSA:
  727. OspfRI.flags &= ~RIFLG_LSA_ENGAGED;
  728. ospf_opaque_lsa_flush_schedule (&lsa);
  729. break;
  730. default:
  731. zlog_warn ("ospf_router_info_lsa_schedule: Unknown opcode (%u)",
  732. opcode);
  733. break;
  734. }
  735. return;
  736. }
  737. /*------------------------------------------------------------------------*
  738. * Followings are vty session control functions.
  739. *------------------------------------------------------------------------*/
  740. static u_int16_t
  741. show_vty_router_cap (struct vty *vty, struct ri_tlv_header *tlvh)
  742. {
  743. struct ri_tlv_router_cap *top = (struct ri_tlv_router_cap *) tlvh;
  744. if (vty != NULL)
  745. vty_out (vty, " Router Capabilities: 0x%x%s", ntohl (top->value),
  746. VTY_NEWLINE);
  747. else
  748. zlog_debug (" Router Capabilities: 0x%x", ntohl (top->value));
  749. return RI_TLV_SIZE (tlvh);
  750. }
  751. static u_int16_t
  752. show_vty_pce_subtlv_address (struct vty *vty, struct ri_tlv_header *tlvh)
  753. {
  754. struct ri_pce_subtlv_address *top = (struct ri_pce_subtlv_address *) tlvh;
  755. if (ntohs (top->address.type) == PCE_ADDRESS_TYPE_IPV4)
  756. {
  757. if (vty != NULL)
  758. vty_out (vty, " PCE Address: %s%s", inet_ntoa (top->address.value),
  759. VTY_NEWLINE);
  760. else
  761. zlog_debug (" PCE Address: %s", inet_ntoa (top->address.value));
  762. }
  763. else
  764. {
  765. /* TODO: Add support to IPv6 with inet_ntop() */
  766. if (vty != NULL)
  767. vty_out (vty, " PCE Address: 0x%x%s",
  768. ntohl (top->address.value.s_addr), VTY_NEWLINE);
  769. else
  770. zlog_debug (" PCE Address: 0x%x",
  771. ntohl (top->address.value.s_addr));
  772. }
  773. return RI_TLV_SIZE (tlvh);
  774. }
  775. static u_int16_t
  776. show_vty_pce_subtlv_path_scope (struct vty *vty, struct ri_tlv_header *tlvh)
  777. {
  778. struct ri_pce_subtlv_path_scope *top =
  779. (struct ri_pce_subtlv_path_scope *) tlvh;
  780. if (vty != NULL)
  781. vty_out (vty, " PCE Path Scope: 0x%x%s", ntohl (top->value),
  782. VTY_NEWLINE);
  783. else
  784. zlog_debug (" PCE Path Scope: 0x%x", ntohl (top->value));
  785. return RI_TLV_SIZE (tlvh);
  786. }
  787. static u_int16_t
  788. show_vty_pce_subtlv_domain (struct vty *vty, struct ri_tlv_header *tlvh)
  789. {
  790. struct ri_pce_subtlv_domain *top = (struct ri_pce_subtlv_domain *) tlvh;
  791. struct in_addr tmp;
  792. if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
  793. {
  794. tmp.s_addr = top->value;
  795. if (vty != NULL)
  796. vty_out (vty, " PCE domain Area: %s%s", inet_ntoa (tmp),
  797. VTY_NEWLINE);
  798. else
  799. zlog_debug (" PCE domain Area: %s", inet_ntoa (tmp));
  800. }
  801. else
  802. {
  803. if (vty != NULL)
  804. vty_out (vty, " PCE domain AS: %d%s", ntohl (top->value),
  805. VTY_NEWLINE);
  806. else
  807. zlog_debug (" PCE domain AS: %d", ntohl (top->value));
  808. }
  809. return RI_TLV_SIZE (tlvh);
  810. }
  811. static u_int16_t
  812. show_vty_pce_subtlv_neighbor (struct vty *vty, struct ri_tlv_header *tlvh)
  813. {
  814. struct ri_pce_subtlv_neighbor *top = (struct ri_pce_subtlv_neighbor *) tlvh;
  815. struct in_addr tmp;
  816. if (ntohs (top->type) == PCE_DOMAIN_TYPE_AREA)
  817. {
  818. tmp.s_addr = top->value;
  819. if (vty != NULL)
  820. vty_out (vty, " PCE neighbor Area: %s%s", inet_ntoa (tmp),
  821. VTY_NEWLINE);
  822. else
  823. zlog_debug (" PCE neighbor Area: %s", inet_ntoa (tmp));
  824. }
  825. else
  826. {
  827. if (vty != NULL)
  828. vty_out (vty, " PCE neighbor AS: %d%s", ntohl (top->value),
  829. VTY_NEWLINE);
  830. else
  831. zlog_debug (" PCE neighbor AS: %d", ntohl (top->value));
  832. }
  833. return RI_TLV_SIZE (tlvh);
  834. }
  835. static u_int16_t
  836. show_vty_pce_subtlv_cap_flag (struct vty *vty, struct ri_tlv_header *tlvh)
  837. {
  838. struct ri_pce_subtlv_cap_flag *top = (struct ri_pce_subtlv_cap_flag *) tlvh;
  839. if (vty != NULL)
  840. vty_out (vty, " PCE Capabilities Flag: 0x%x%s", ntohl (top->value),
  841. VTY_NEWLINE);
  842. else
  843. zlog_debug (" PCE Capabilities Flag: 0x%x", ntohl (top->value));
  844. return RI_TLV_SIZE (tlvh);
  845. }
  846. static u_int16_t
  847. show_vty_unknown_tlv (struct vty *vty, struct ri_tlv_header *tlvh)
  848. {
  849. if (vty != NULL)
  850. vty_out (vty, " Unknown TLV: [type(0x%x), length(0x%x)]%s",
  851. ntohs (tlvh->type), ntohs (tlvh->length), VTY_NEWLINE);
  852. else
  853. zlog_debug (" Unknown TLV: [type(0x%x), length(0x%x)]",
  854. ntohs (tlvh->type), ntohs (tlvh->length));
  855. return RI_TLV_SIZE (tlvh);
  856. }
  857. static u_int16_t
  858. show_vty_pce_info (struct vty *vty, struct ri_tlv_header *ri, uint32_t total)
  859. {
  860. struct ri_tlv_header *tlvh;
  861. u_int16_t sum = 0;
  862. for (tlvh = ri; sum < total; tlvh = RI_TLV_HDR_NEXT (tlvh))
  863. {
  864. switch (ntohs (tlvh->type))
  865. {
  866. case RI_PCE_SUBTLV_ADDRESS:
  867. sum += show_vty_pce_subtlv_address (vty, tlvh);
  868. break;
  869. case RI_PCE_SUBTLV_PATH_SCOPE:
  870. sum += show_vty_pce_subtlv_path_scope (vty, tlvh);
  871. break;
  872. case RI_PCE_SUBTLV_DOMAIN:
  873. sum += show_vty_pce_subtlv_domain (vty, tlvh);
  874. break;
  875. case RI_PCE_SUBTLV_NEIGHBOR:
  876. sum += show_vty_pce_subtlv_neighbor (vty, tlvh);
  877. break;
  878. case RI_PCE_SUBTLV_CAP_FLAG:
  879. sum += show_vty_pce_subtlv_cap_flag (vty, tlvh);
  880. break;
  881. default:
  882. sum += show_vty_unknown_tlv (vty, tlvh);
  883. break;
  884. }
  885. }
  886. return sum;
  887. }
  888. static void
  889. ospf_router_info_show_info (struct vty *vty, struct ospf_lsa *lsa)
  890. {
  891. struct lsa_header *lsah = (struct lsa_header *) lsa->data;
  892. struct ri_tlv_header *tlvh;
  893. u_int16_t length = 0, sum = 0;
  894. /* Initialize TLV browsing */
  895. length = ntohs (lsah->length) - OSPF_LSA_HEADER_SIZE;
  896. for (tlvh = RI_TLV_HDR_TOP (lsah); sum < length;
  897. tlvh = RI_TLV_HDR_NEXT (tlvh))
  898. {
  899. switch (ntohs (tlvh->type))
  900. {
  901. case RI_TLV_CAPABILITIES:
  902. sum += show_vty_router_cap (vty, tlvh);
  903. break;
  904. case RI_TLV_PCE:
  905. tlvh++;
  906. sum += RI_TLV_HDR_SIZE;
  907. sum += show_vty_pce_info (vty, tlvh, length - sum);
  908. break;
  909. default:
  910. sum += show_vty_unknown_tlv (vty, tlvh);
  911. break;
  912. }
  913. }
  914. return;
  915. }
  916. static void
  917. ospf_router_info_config_write_router (struct vty *vty)
  918. {
  919. struct ospf_pce_info *pce = &OspfRI.pce_info;
  920. struct listnode *node;
  921. struct ri_pce_subtlv_domain *domain;
  922. struct ri_pce_subtlv_neighbor *neighbor;
  923. struct in_addr tmp;
  924. if (OspfRI.status == enabled)
  925. {
  926. if (OspfRI.scope == OSPF_OPAQUE_AS_LSA)
  927. vty_out (vty, " router-info as%s", VTY_NEWLINE);
  928. else
  929. vty_out (vty, " router-info area %s%s", inet_ntoa (OspfRI.area_id),
  930. VTY_NEWLINE);
  931. if (pce->pce_address.header.type != 0)
  932. vty_out (vty, " pce address %s%s",
  933. inet_ntoa (pce->pce_address.address.value), VTY_NEWLINE);
  934. if (pce->pce_cap_flag.header.type != 0)
  935. vty_out (vty, " pce flag 0x%x%s", ntohl (pce->pce_cap_flag.value),
  936. VTY_NEWLINE);
  937. for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
  938. {
  939. if (domain->header.type != 0)
  940. {
  941. if (domain->type == PCE_DOMAIN_TYPE_AREA)
  942. {
  943. tmp.s_addr = domain->value;
  944. vty_out (vty, " pce domain area %s%s", inet_ntoa (tmp),
  945. VTY_NEWLINE);
  946. }
  947. else
  948. {
  949. vty_out (vty, " pce domain as %d%s", ntohl (domain->value),
  950. VTY_NEWLINE);
  951. }
  952. }
  953. }
  954. for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
  955. {
  956. if (neighbor->header.type != 0)
  957. {
  958. if (neighbor->type == PCE_DOMAIN_TYPE_AREA)
  959. {
  960. tmp.s_addr = neighbor->value;
  961. vty_out (vty, " pce neighbor area %s%s", inet_ntoa (tmp),
  962. VTY_NEWLINE);
  963. }
  964. else
  965. {
  966. vty_out (vty, " pce neighbor as %d%s",
  967. ntohl (neighbor->value), VTY_NEWLINE);
  968. }
  969. }
  970. }
  971. if (pce->pce_scope.header.type != 0)
  972. vty_out (vty, " pce scope 0x%x%s",
  973. ntohl (OspfRI.pce_info.pce_scope.value), VTY_NEWLINE);
  974. }
  975. return;
  976. }
  977. /*------------------------------------------------------------------------*
  978. * Followings are vty command functions.
  979. *------------------------------------------------------------------------*/
  980. DEFUN (router_info,
  981. router_info_area_cmd,
  982. "router-info area A.B.C.D",
  983. OSPF_RI_STR
  984. "Enable the Router Information functionality with Area flooding scope\n"
  985. "OSPF area ID in IP format")
  986. {
  987. u_int8_t scope;
  988. if (OspfRI.status == enabled)
  989. return CMD_SUCCESS;
  990. /* Check and get Area value if present */
  991. if (argc == 1)
  992. {
  993. if (!inet_aton (argv[0], &OspfRI.area_id))
  994. {
  995. vty_out (vty, "Please specify Router Info Area by A.B.C.D%s",
  996. VTY_NEWLINE);
  997. return CMD_WARNING;
  998. }
  999. scope = OSPF_OPAQUE_AREA_LSA;
  1000. }
  1001. else
  1002. {
  1003. OspfRI.area_id.s_addr = 0;
  1004. scope = OSPF_OPAQUE_AS_LSA;
  1005. }
  1006. /* First start to register Router Information callbacks */
  1007. if ((ospf_router_info_register (scope)) != 0)
  1008. {
  1009. zlog_warn ("Enable to register Router Information callbacks. Abort!");
  1010. return CMD_WARNING;
  1011. }
  1012. OspfRI.status = enabled;
  1013. if (IS_DEBUG_OSPF_EVENT)
  1014. zlog_debug ("RI-> Router Information (%s flooding): OFF -> ON",
  1015. OspfRI.scope == OSPF_OPAQUE_AREA_LSA ? "Area" : "AS");
  1016. /*
  1017. * Following code is intended to handle two cases;
  1018. *
  1019. * 1) Router Information was disabled at startup time, but now become enabled.
  1020. * 2) Router Information was once enabled then disabled, and now enabled again.
  1021. */
  1022. initialize_params (&OspfRI);
  1023. /* Refresh RI LSA if already engaged */
  1024. if (OspfRI.flags & RIFLG_LSA_ENGAGED)
  1025. {
  1026. zlog_debug ("RI-> Initial origination following configuration");
  1027. ospf_router_info_lsa_schedule (REORIGINATE_THIS_LSA);
  1028. }
  1029. return CMD_SUCCESS;
  1030. }
  1031. ALIAS (router_info,
  1032. router_info_as_cmd,
  1033. "router-info as",
  1034. OSPF_RI_STR
  1035. "Enable the Router Information functionality with AS flooding scope\n")
  1036. DEFUN (no_router_info,
  1037. no_router_info_cmd,
  1038. "no router-info",
  1039. NO_STR
  1040. "Disable the Router Information functionality\n")
  1041. {
  1042. if (OspfRI.status == disabled)
  1043. return CMD_SUCCESS;
  1044. if (IS_DEBUG_OSPF_EVENT)
  1045. zlog_debug ("RI-> Router Information: ON -> OFF");
  1046. if (OspfRI.flags & RIFLG_LSA_ENGAGED)
  1047. ospf_router_info_lsa_schedule (FLUSH_THIS_LSA);
  1048. /* Unregister the callbacks */
  1049. ospf_router_info_unregister ();
  1050. OspfRI.status = disabled;
  1051. return CMD_SUCCESS;
  1052. }
  1053. DEFUN (pce_address,
  1054. pce_address_cmd,
  1055. "pce address A.B.C.D",
  1056. PCE_STR
  1057. "Stable IP address of the PCE\n"
  1058. "PCE address in IPv4 address format\n")
  1059. {
  1060. struct in_addr value;
  1061. struct ospf_pce_info *pi = &OspfRI.pce_info;
  1062. if (!inet_aton (argv[0], &value))
  1063. {
  1064. vty_out (vty, "Please specify PCE Address by A.B.C.D%s", VTY_NEWLINE);
  1065. return CMD_WARNING;
  1066. }
  1067. if (ntohs (pi->pce_address.header.type) == 0
  1068. || ntohl (pi->pce_address.address.value.s_addr) != ntohl (value.s_addr))
  1069. {
  1070. set_pce_address (value, pi);
  1071. /* Refresh RI LSA if already engaged */
  1072. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1073. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1074. }
  1075. return CMD_SUCCESS;
  1076. }
  1077. DEFUN (no_pce_address,
  1078. no_pce_address_cmd,
  1079. "no pce address",
  1080. NO_STR
  1081. PCE_STR
  1082. "Disable PCE address\n")
  1083. {
  1084. unset_param (&OspfRI.pce_info.pce_address.header);
  1085. /* Refresh RI LSA if already engaged */
  1086. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1087. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1088. return CMD_SUCCESS;
  1089. }
  1090. DEFUN (pce_path_scope,
  1091. pce_path_scope_cmd,
  1092. "pce scope BITPATTERN",
  1093. PCE_STR
  1094. "Path scope visibilities of the PCE for path computation\n"
  1095. "32-bit Hexadecimal value\n")
  1096. {
  1097. uint32_t scope;
  1098. struct ospf_pce_info *pi = &OspfRI.pce_info;
  1099. if (sscanf (argv[0], "0x%x", &scope) != 1)
  1100. {
  1101. vty_out (vty, "pce_path_scope: fscanf: %s%s", safe_strerror (errno),
  1102. VTY_NEWLINE);
  1103. return CMD_WARNING;
  1104. }
  1105. if (ntohl (pi->pce_scope.header.type) == 0 || scope != pi->pce_scope.value)
  1106. {
  1107. set_pce_path_scope (scope, pi);
  1108. /* Refresh RI LSA if already engaged */
  1109. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1110. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1111. }
  1112. return CMD_SUCCESS;
  1113. }
  1114. DEFUN (no_pce_path_scope,
  1115. no_pce_path_scope_cmd,
  1116. "no pce scope",
  1117. NO_STR
  1118. PCE_STR
  1119. "Disable PCE path scope\n")
  1120. {
  1121. unset_param (&OspfRI.pce_info.pce_address.header);
  1122. /* Refresh RI LSA if already engaged */
  1123. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1124. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1125. return CMD_SUCCESS;
  1126. }
  1127. DEFUN (pce_domain,
  1128. pce_domain_cmd,
  1129. "pce domain as <0-65535>",
  1130. PCE_STR
  1131. "Configure PCE domain AS number\n"
  1132. "AS number where the PCE as visibilities for path computation\n"
  1133. "AS number in decimal <0-65535>\n")
  1134. {
  1135. uint32_t as;
  1136. struct ospf_pce_info *pce = &OspfRI.pce_info;
  1137. struct listnode *node;
  1138. struct ri_pce_subtlv_domain *domain;
  1139. if (sscanf (argv[0], "%d", &as) != 1)
  1140. {
  1141. vty_out (vty, "pce_domain: fscanf: %s%s", safe_strerror (errno),
  1142. VTY_NEWLINE);
  1143. return CMD_WARNING;
  1144. }
  1145. /* Check if the domain is not already in the domain list */
  1146. for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
  1147. {
  1148. if (ntohl (domain->header.type) == 0 && as == domain->value)
  1149. goto out;
  1150. }
  1151. /* Create new domain if not found */
  1152. set_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
  1153. /* Refresh RI LSA if already engaged */
  1154. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1155. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1156. out:return CMD_SUCCESS;
  1157. }
  1158. DEFUN (no_pce_domain,
  1159. no_pce_domain_cmd,
  1160. "no pce domain as <0-65535>",
  1161. NO_STR
  1162. PCE_STR
  1163. "Disable PCE domain AS number\n"
  1164. "AS number where the PCE as visibilities for path computation\n"
  1165. "AS number in decimal <0-65535>\n")
  1166. {
  1167. uint32_t as;
  1168. struct ospf_pce_info *pce = &OspfRI.pce_info;
  1169. if (sscanf (argv[0], "%d", &as) != 1)
  1170. {
  1171. vty_out (vty, "no_pce_domain: fscanf: %s%s", safe_strerror (errno),
  1172. VTY_NEWLINE);
  1173. return CMD_WARNING;
  1174. }
  1175. /* Unset corresponding PCE domain */
  1176. unset_pce_domain (PCE_DOMAIN_TYPE_AS, as, pce);
  1177. /* Refresh RI LSA if already engaged */
  1178. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1179. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1180. return CMD_SUCCESS;
  1181. }
  1182. DEFUN (pce_neigbhor,
  1183. pce_neighbor_cmd,
  1184. "pce neighbor as <0-65535>",
  1185. PCE_STR
  1186. "Configure PCE neighbor domain AS number\n"
  1187. "AS number of PCE neighbors\n"
  1188. "AS number in decimal <0-65535>\n")
  1189. {
  1190. uint32_t as;
  1191. struct ospf_pce_info *pce = &OspfRI.pce_info;
  1192. struct listnode *node;
  1193. struct ri_pce_subtlv_neighbor *neighbor;
  1194. if (sscanf (argv[0], "%d", &as) != 1)
  1195. {
  1196. vty_out (vty, "pce_neighbor: fscanf: %s%s", safe_strerror (errno),
  1197. VTY_NEWLINE);
  1198. return CMD_WARNING;
  1199. }
  1200. /* Check if the domain is not already in the domain list */
  1201. for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
  1202. {
  1203. if (ntohl (neighbor->header.type) == 0 && as == neighbor->value)
  1204. goto out;
  1205. }
  1206. /* Create new domain if not found */
  1207. set_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
  1208. /* Refresh RI LSA if already engaged */
  1209. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1210. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1211. out:return CMD_SUCCESS;
  1212. }
  1213. DEFUN (no_pce_neighbor,
  1214. no_pce_neighbor_cmd,
  1215. "no pce neighbor as <0-65535>",
  1216. NO_STR
  1217. PCE_STR
  1218. "Disable PCE neighbor AS number\n"
  1219. "AS number of PCE neighbor\n"
  1220. "AS number in decimal <0-65535>\n")
  1221. {
  1222. uint32_t as;
  1223. struct ospf_pce_info *pce = &OspfRI.pce_info;
  1224. if (sscanf (argv[0], "%d", &as) != 1)
  1225. {
  1226. vty_out (vty, "no_pce_neighbor: fscanf: %s%s", safe_strerror (errno),
  1227. VTY_NEWLINE);
  1228. return CMD_WARNING;
  1229. }
  1230. /* Unset corresponding PCE domain */
  1231. unset_pce_neighbor (PCE_DOMAIN_TYPE_AS, as, pce);
  1232. /* Refresh RI LSA if already engaged */
  1233. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1234. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1235. return CMD_SUCCESS;
  1236. }
  1237. DEFUN (pce_cap_flag,
  1238. pce_cap_flag_cmd,
  1239. "pce flag BITPATTERN",
  1240. PCE_STR
  1241. "Capabilities of the PCE for path computation\n"
  1242. "32-bit Hexadecimal value\n")
  1243. {
  1244. uint32_t cap;
  1245. struct ospf_pce_info *pce = &OspfRI.pce_info;
  1246. if (sscanf (argv[0], "0x%x", &cap) != 1)
  1247. {
  1248. vty_out (vty, "pce_cap_flag: fscanf: %s%s", safe_strerror (errno),
  1249. VTY_NEWLINE);
  1250. return CMD_WARNING;
  1251. }
  1252. if (ntohl (pce->pce_cap_flag.header.type) == 0
  1253. || cap != pce->pce_cap_flag.value)
  1254. {
  1255. set_pce_cap_flag (cap, pce);
  1256. /* Refresh RI LSA if already engaged */
  1257. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1258. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1259. }
  1260. return CMD_SUCCESS;
  1261. }
  1262. DEFUN (no_pce_cap_flag,
  1263. no_pce_cap_flag_cmd,
  1264. "no pce flag",
  1265. NO_STR
  1266. PCE_STR
  1267. "Disable PCE capabilities\n")
  1268. {
  1269. unset_param (&OspfRI.pce_info.pce_cap_flag.header);
  1270. /* Refresh RI LSA if already engaged */
  1271. if ((OspfRI.status == enabled) && (OspfRI.flags & RIFLG_LSA_ENGAGED))
  1272. ospf_router_info_lsa_schedule (REFRESH_THIS_LSA);
  1273. return CMD_SUCCESS;
  1274. }
  1275. DEFUN (show_ip_ospf_router_info,
  1276. show_ip_ospf_router_info_cmd,
  1277. "show ip ospf router-info",
  1278. SHOW_STR
  1279. IP_STR
  1280. OSPF_STR
  1281. "Router Information\n")
  1282. {
  1283. if (OspfRI.status == enabled)
  1284. {
  1285. vty_out (vty, "--- Router Information parameters ---%s", VTY_NEWLINE);
  1286. show_vty_router_cap (vty, &OspfRI.router_cap.header);
  1287. }
  1288. else
  1289. {
  1290. if (vty != NULL)
  1291. vty_out (vty, " Router Information is disabled on this router%s", VTY_NEWLINE);
  1292. }
  1293. return CMD_SUCCESS;
  1294. }
  1295. DEFUN (show_ip_opsf_router_info_pce,
  1296. show_ip_ospf_router_info_pce_cmd,
  1297. "show ip ospf router-info pce",
  1298. SHOW_STR
  1299. IP_STR
  1300. OSPF_STR
  1301. "Router Information\n"
  1302. "PCE information\n")
  1303. {
  1304. struct ospf_pce_info *pce = &OspfRI.pce_info;
  1305. struct listnode *node;
  1306. struct ri_pce_subtlv_domain *domain;
  1307. struct ri_pce_subtlv_neighbor *neighbor;
  1308. if (OspfRI.status == enabled)
  1309. {
  1310. vty_out (vty, "--- PCE parameters ---%s", VTY_NEWLINE);
  1311. if (pce->pce_address.header.type != 0)
  1312. show_vty_pce_subtlv_address (vty, &pce->pce_address.header);
  1313. if (pce->pce_scope.header.type != 0)
  1314. show_vty_pce_subtlv_path_scope (vty, &pce->pce_scope.header);
  1315. for (ALL_LIST_ELEMENTS_RO (pce->pce_domain, node, domain))
  1316. {
  1317. if (domain->header.type != 0)
  1318. show_vty_pce_subtlv_domain (vty, &domain->header);
  1319. }
  1320. for (ALL_LIST_ELEMENTS_RO (pce->pce_neighbor, node, neighbor))
  1321. {
  1322. if (neighbor->header.type != 0)
  1323. show_vty_pce_subtlv_neighbor (vty, &neighbor->header);
  1324. }
  1325. if (pce->pce_cap_flag.header.type != 0)
  1326. show_vty_pce_subtlv_cap_flag (vty, &pce->pce_cap_flag.header);
  1327. }
  1328. else
  1329. {
  1330. vty_out (vty, " Router Information is disabled on this router%s",
  1331. VTY_NEWLINE);
  1332. }
  1333. return CMD_SUCCESS;
  1334. }
  1335. /* Install new CLI commands */
  1336. static void
  1337. ospf_router_info_register_vty (void)
  1338. {
  1339. install_element (VIEW_NODE, &show_ip_ospf_router_info_cmd);
  1340. install_element (VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
  1341. install_element (OSPF_NODE, &router_info_area_cmd);
  1342. install_element (OSPF_NODE, &router_info_as_cmd);
  1343. install_element (OSPF_NODE, &no_router_info_cmd);
  1344. install_element (OSPF_NODE, &pce_address_cmd);
  1345. install_element (OSPF_NODE, &pce_path_scope_cmd);
  1346. install_element (OSPF_NODE, &pce_domain_cmd);
  1347. install_element (OSPF_NODE, &no_pce_domain_cmd);
  1348. install_element (OSPF_NODE, &pce_neighbor_cmd);
  1349. install_element (OSPF_NODE, &no_pce_neighbor_cmd);
  1350. install_element (OSPF_NODE, &pce_cap_flag_cmd);
  1351. return;
  1352. }