isis_circuit.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. /*
  2. * IS-IS Rout(e)ing protocol - isis_circuit.h
  3. *
  4. * Copyright (C) 2001,2002 Sampo Saaristo
  5. * Tampere University of Technology
  6. * Institute of Communications Engineering
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public Licenseas published by the Free
  10. * Software Foundation; either version 2 of the License, or (at your option)
  11. * any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. * more details.
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #ifdef GNU_LINUX
  23. #include <net/ethernet.h>
  24. #else
  25. #include <netinet/if_ether.h>
  26. #endif
  27. #ifndef ETHER_ADDR_LEN
  28. #define ETHER_ADDR_LEN ETHERADDRL
  29. #endif
  30. #include "log.h"
  31. #include "memory.h"
  32. #include "if.h"
  33. #include "linklist.h"
  34. #include "command.h"
  35. #include "thread.h"
  36. #include "vty.h"
  37. #include "hash.h"
  38. #include "prefix.h"
  39. #include "stream.h"
  40. #include "isisd/dict.h"
  41. #include "isisd/include-netbsd/iso.h"
  42. #include "isisd/isis_constants.h"
  43. #include "isisd/isis_common.h"
  44. #include "isisd/isis_flags.h"
  45. #include "isisd/isis_circuit.h"
  46. #include "isisd/isis_tlv.h"
  47. #include "isisd/isis_lsp.h"
  48. #include "isisd/isis_pdu.h"
  49. #include "isisd/isis_network.h"
  50. #include "isisd/isis_misc.h"
  51. #include "isisd/isis_constants.h"
  52. #include "isisd/isis_adjacency.h"
  53. #include "isisd/isis_dr.h"
  54. #include "isisd/isisd.h"
  55. #include "isisd/isis_csm.h"
  56. #include "isisd/isis_events.h"
  57. #include "isisd/isis_te.h"
  58. /*
  59. * Prototypes.
  60. */
  61. int isis_interface_config_write(struct vty *);
  62. int isis_if_new_hook(struct interface *);
  63. int isis_if_delete_hook(struct interface *);
  64. struct isis_circuit *
  65. isis_circuit_new ()
  66. {
  67. struct isis_circuit *circuit;
  68. int i;
  69. circuit = XCALLOC (MTYPE_ISIS_CIRCUIT, sizeof (struct isis_circuit));
  70. if (circuit == NULL)
  71. {
  72. zlog_err ("Can't malloc isis circuit");
  73. return NULL;
  74. }
  75. /*
  76. * Default values
  77. */
  78. circuit->is_type = IS_LEVEL_1_AND_2;
  79. circuit->flags = 0;
  80. circuit->pad_hellos = 1;
  81. for (i = 0; i < 2; i++)
  82. {
  83. circuit->hello_interval[i] = DEFAULT_HELLO_INTERVAL;
  84. circuit->hello_multiplier[i] = DEFAULT_HELLO_MULTIPLIER;
  85. circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL;
  86. circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL;
  87. circuit->priority[i] = DEFAULT_PRIORITY;
  88. circuit->metric[i] = DEFAULT_CIRCUIT_METRIC;
  89. circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC;
  90. }
  91. circuit->mtc = mpls_te_circuit_new();
  92. return circuit;
  93. }
  94. void
  95. isis_circuit_del (struct isis_circuit *circuit)
  96. {
  97. if (!circuit)
  98. return;
  99. isis_circuit_if_unbind (circuit, circuit->interface);
  100. /* and lastly the circuit itself */
  101. XFREE (MTYPE_ISIS_CIRCUIT, circuit);
  102. return;
  103. }
  104. void
  105. isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
  106. {
  107. assert (area);
  108. circuit->area = area;
  109. /*
  110. * Whenever the is-type of an area is changed, the is-type of each circuit
  111. * in that area is updated to a non-empty subset of the area is-type.
  112. * Inversely, when configuring a new circuit, this property should be
  113. * ensured as well.
  114. */
  115. if (area->is_type != IS_LEVEL_1_AND_2)
  116. circuit->is_type = area->is_type;
  117. /*
  118. * Add the circuit into area
  119. */
  120. listnode_add (area->circuit_list, circuit);
  121. circuit->idx = flags_get_index (&area->flags);
  122. return;
  123. }
  124. void
  125. isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area)
  126. {
  127. /* Free the index of SRM and SSN flags */
  128. flags_free_index (&area->flags, circuit->idx);
  129. circuit->idx = 0;
  130. /* Remove circuit from area */
  131. assert (circuit->area == area);
  132. listnode_delete (area->circuit_list, circuit);
  133. circuit->area = NULL;
  134. return;
  135. }
  136. struct isis_circuit *
  137. circuit_lookup_by_ifp (struct interface *ifp, struct list *list)
  138. {
  139. struct isis_circuit *circuit = NULL;
  140. struct listnode *node;
  141. if (!list)
  142. return NULL;
  143. for (ALL_LIST_ELEMENTS_RO (list, node, circuit))
  144. if (circuit->interface == ifp)
  145. {
  146. assert (ifp->info == circuit);
  147. return circuit;
  148. }
  149. return NULL;
  150. }
  151. struct isis_circuit *
  152. circuit_scan_by_ifp (struct interface *ifp)
  153. {
  154. struct isis_area *area;
  155. struct listnode *node;
  156. struct isis_circuit *circuit;
  157. if (ifp->info)
  158. return (struct isis_circuit *)ifp->info;
  159. if (isis->area_list)
  160. {
  161. for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
  162. {
  163. circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
  164. if (circuit)
  165. return circuit;
  166. }
  167. }
  168. return circuit_lookup_by_ifp (ifp, isis->init_circ_list);
  169. }
  170. void
  171. isis_circuit_add_addr (struct isis_circuit *circuit,
  172. struct connected *connected)
  173. {
  174. struct listnode *node;
  175. struct prefix_ipv4 *ipv4;
  176. u_char buf[BUFSIZ];
  177. #ifdef HAVE_IPV6
  178. struct prefix_ipv6 *ipv6;
  179. #endif /* HAVE_IPV6 */
  180. memset (&buf, 0, BUFSIZ);
  181. if (connected->address->family == AF_INET)
  182. {
  183. u_int32_t addr = connected->address->u.prefix4.s_addr;
  184. addr = ntohl (addr);
  185. if (IPV4_NET0(addr) ||
  186. IPV4_NET127(addr) ||
  187. IN_CLASSD(addr) ||
  188. IPV4_LINKLOCAL(addr))
  189. return;
  190. for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ipv4))
  191. if (prefix_same ((struct prefix *) ipv4, connected->address))
  192. return;
  193. ipv4 = prefix_ipv4_new ();
  194. ipv4->prefixlen = connected->address->prefixlen;
  195. ipv4->prefix = connected->address->u.prefix4;
  196. listnode_add (circuit->ip_addrs, ipv4);
  197. /* Update MPLS TE Local IP address parameter */
  198. set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix);
  199. if (circuit->area)
  200. lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
  201. #ifdef EXTREME_DEBUG
  202. prefix2str (connected->address, buf, BUFSIZ);
  203. zlog_debug ("Added IP address %s to circuit %d", buf,
  204. circuit->circuit_id);
  205. #endif /* EXTREME_DEBUG */
  206. }
  207. #ifdef HAVE_IPV6
  208. if (connected->address->family == AF_INET6)
  209. {
  210. if (IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6))
  211. return;
  212. for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ipv6))
  213. if (prefix_same ((struct prefix *) ipv6, connected->address))
  214. return;
  215. for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ipv6))
  216. if (prefix_same ((struct prefix *) ipv6, connected->address))
  217. return;
  218. ipv6 = prefix_ipv6_new ();
  219. ipv6->prefixlen = connected->address->prefixlen;
  220. ipv6->prefix = connected->address->u.prefix6;
  221. if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
  222. listnode_add (circuit->ipv6_link, ipv6);
  223. else
  224. listnode_add (circuit->ipv6_non_link, ipv6);
  225. if (circuit->area)
  226. lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
  227. #ifdef EXTREME_DEBUG
  228. prefix2str (connected->address, buf, BUFSIZ);
  229. zlog_debug ("Added IPv6 address %s to circuit %d", buf,
  230. circuit->circuit_id);
  231. #endif /* EXTREME_DEBUG */
  232. }
  233. #endif /* HAVE_IPV6 */
  234. return;
  235. }
  236. void
  237. isis_circuit_del_addr (struct isis_circuit *circuit,
  238. struct connected *connected)
  239. {
  240. struct prefix_ipv4 *ipv4, *ip = NULL;
  241. struct listnode *node;
  242. u_char buf[BUFSIZ];
  243. #ifdef HAVE_IPV6
  244. struct prefix_ipv6 *ipv6, *ip6 = NULL;
  245. int found = 0;
  246. #endif /* HAVE_IPV6 */
  247. memset (&buf, 0, BUFSIZ);
  248. if (connected->address->family == AF_INET)
  249. {
  250. ipv4 = prefix_ipv4_new ();
  251. ipv4->prefixlen = connected->address->prefixlen;
  252. ipv4->prefix = connected->address->u.prefix4;
  253. for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip))
  254. if (prefix_same ((struct prefix *) ip, (struct prefix *) ipv4))
  255. break;
  256. if (ip)
  257. {
  258. listnode_delete (circuit->ip_addrs, ip);
  259. if (circuit->area)
  260. lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
  261. }
  262. else
  263. {
  264. prefix2str (connected->address, (char *)buf, BUFSIZ);
  265. zlog_warn ("Nonexitant ip address %s removal attempt from \
  266. circuit %d", buf, circuit->circuit_id);
  267. zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
  268. for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ip))
  269. {
  270. prefix2str((struct prefix*)ip, (char *)buf, BUFSIZ);
  271. zlog_warn(" %s", buf);
  272. }
  273. zlog_warn("End of addresses");
  274. }
  275. prefix_ipv4_free (ipv4);
  276. }
  277. #ifdef HAVE_IPV6
  278. if (connected->address->family == AF_INET6)
  279. {
  280. ipv6 = prefix_ipv6_new ();
  281. ipv6->prefixlen = connected->address->prefixlen;
  282. ipv6->prefix = connected->address->u.prefix6;
  283. if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
  284. {
  285. for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ip6))
  286. {
  287. if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6))
  288. break;
  289. }
  290. if (ip6)
  291. {
  292. listnode_delete (circuit->ipv6_link, ip6);
  293. found = 1;
  294. }
  295. }
  296. else
  297. {
  298. for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ip6))
  299. {
  300. if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6))
  301. break;
  302. }
  303. if (ip6)
  304. {
  305. listnode_delete (circuit->ipv6_non_link, ip6);
  306. found = 1;
  307. }
  308. }
  309. if (!found)
  310. {
  311. prefix2str (connected->address, (char *)buf, BUFSIZ);
  312. zlog_warn ("Nonexitant ip address %s removal attempt from \
  313. circuit %d", buf, circuit->circuit_id);
  314. zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
  315. for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip6))
  316. {
  317. prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ);
  318. zlog_warn(" %s", buf);
  319. }
  320. zlog_warn(" -----");
  321. for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip6))
  322. {
  323. prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ);
  324. zlog_warn(" %s", buf);
  325. }
  326. zlog_warn("End of addresses");
  327. }
  328. else if (circuit->area)
  329. lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
  330. prefix_ipv6_free (ipv6);
  331. }
  332. #endif /* HAVE_IPV6 */
  333. return;
  334. }
  335. static u_char
  336. isis_circuit_id_gen (struct interface *ifp)
  337. {
  338. u_char id = 0;
  339. char ifname[16];
  340. unsigned int i;
  341. int start = -1, end = -1;
  342. /*
  343. * Get a stable circuit id from ifname. This makes
  344. * the ifindex from flapping when netdevs are created
  345. * and deleted on the fly. Note that this circuit id
  346. * is used in pseudo lsps so it is better to be stable.
  347. * The following code works on any reasonanle ifname
  348. * like: eth1 or trk-1.1 etc.
  349. */
  350. for (i = 0; i < strlen (ifp->name); i++)
  351. {
  352. if (isdigit((unsigned char)ifp->name[i]))
  353. {
  354. if (start < 0)
  355. {
  356. start = i;
  357. end = i + 1;
  358. }
  359. else
  360. {
  361. end = i + 1;
  362. }
  363. }
  364. else if (start >= 0)
  365. break;
  366. }
  367. if ((start >= 0) && (end >= start) && (end - start) < 16)
  368. {
  369. memset (ifname, 0, 16);
  370. strncpy (ifname, &ifp->name[start], end - start);
  371. id = (u_char)atoi(ifname);
  372. }
  373. /* Try to be unique. */
  374. if (!id)
  375. id = (u_char)((ifp->ifindex & 0xff) | 0x80);
  376. return id;
  377. }
  378. void
  379. isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp)
  380. {
  381. struct listnode *node, *nnode;
  382. struct connected *conn;
  383. circuit->circuit_id = isis_circuit_id_gen (ifp);
  384. isis_circuit_if_bind (circuit, ifp);
  385. /* isis_circuit_update_addrs (circuit, ifp); */
  386. if (if_is_broadcast (ifp))
  387. {
  388. if (circuit->circ_type_config == CIRCUIT_T_P2P)
  389. circuit->circ_type = CIRCUIT_T_P2P;
  390. else
  391. circuit->circ_type = CIRCUIT_T_BROADCAST;
  392. }
  393. else if (if_is_pointopoint (ifp))
  394. {
  395. circuit->circ_type = CIRCUIT_T_P2P;
  396. }
  397. else if (if_is_loopback (ifp))
  398. {
  399. circuit->circ_type = CIRCUIT_T_LOOPBACK;
  400. circuit->is_passive = 1;
  401. }
  402. else
  403. {
  404. /* It's normal in case of loopback etc. */
  405. if (isis->debugs & DEBUG_EVENTS)
  406. zlog_debug ("isis_circuit_if_add: unsupported media");
  407. circuit->circ_type = CIRCUIT_T_UNKNOWN;
  408. }
  409. circuit->ip_addrs = list_new ();
  410. #ifdef HAVE_IPV6
  411. circuit->ipv6_link = list_new ();
  412. circuit->ipv6_non_link = list_new ();
  413. #endif /* HAVE_IPV6 */
  414. for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
  415. isis_circuit_add_addr (circuit, conn);
  416. return;
  417. }
  418. void
  419. isis_circuit_if_del (struct isis_circuit *circuit, struct interface *ifp)
  420. {
  421. struct listnode *node, *nnode;
  422. struct connected *conn;
  423. assert (circuit->interface == ifp);
  424. /* destroy addresses */
  425. for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
  426. isis_circuit_del_addr (circuit, conn);
  427. if (circuit->ip_addrs)
  428. {
  429. assert (listcount(circuit->ip_addrs) == 0);
  430. list_delete (circuit->ip_addrs);
  431. circuit->ip_addrs = NULL;
  432. }
  433. #ifdef HAVE_IPV6
  434. if (circuit->ipv6_link)
  435. {
  436. assert (listcount(circuit->ipv6_link) == 0);
  437. list_delete (circuit->ipv6_link);
  438. circuit->ipv6_link = NULL;
  439. }
  440. if (circuit->ipv6_non_link)
  441. {
  442. assert (listcount(circuit->ipv6_non_link) == 0);
  443. list_delete (circuit->ipv6_non_link);
  444. circuit->ipv6_non_link = NULL;
  445. }
  446. #endif /* HAVE_IPV6 */
  447. circuit->circ_type = CIRCUIT_T_UNKNOWN;
  448. circuit->circuit_id = 0;
  449. return;
  450. }
  451. void
  452. isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp)
  453. {
  454. assert (circuit != NULL);
  455. assert (ifp != NULL);
  456. if (circuit->interface)
  457. assert (circuit->interface == ifp);
  458. else
  459. circuit->interface = ifp;
  460. if (ifp->info)
  461. assert (ifp->info == circuit);
  462. else
  463. ifp->info = circuit;
  464. isis_link_params_update (circuit, ifp);
  465. }
  466. void
  467. isis_circuit_if_unbind (struct isis_circuit *circuit, struct interface *ifp)
  468. {
  469. assert (circuit != NULL);
  470. assert (ifp != NULL);
  471. assert (circuit->interface == ifp);
  472. assert (ifp->info == circuit);
  473. circuit->interface = NULL;
  474. ifp->info = NULL;
  475. }
  476. static void
  477. isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set)
  478. {
  479. struct isis_area *area;
  480. struct isis_lsp *lsp;
  481. dnode_t *dnode, *dnode_next;
  482. int level;
  483. assert (circuit);
  484. area = circuit->area;
  485. assert (area);
  486. for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++)
  487. {
  488. if (level & circuit->is_type)
  489. {
  490. if (area->lspdb[level - 1] &&
  491. dict_count (area->lspdb[level - 1]) > 0)
  492. {
  493. for (dnode = dict_first (area->lspdb[level - 1]);
  494. dnode != NULL; dnode = dnode_next)
  495. {
  496. dnode_next = dict_next (area->lspdb[level - 1], dnode);
  497. lsp = dnode_get (dnode);
  498. if (is_set)
  499. {
  500. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  501. }
  502. else
  503. {
  504. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  505. }
  506. }
  507. }
  508. }
  509. }
  510. }
  511. size_t
  512. isis_circuit_pdu_size(struct isis_circuit *circuit)
  513. {
  514. return ISO_MTU(circuit);
  515. }
  516. void
  517. isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
  518. {
  519. size_t stream_size = isis_circuit_pdu_size(circuit);
  520. if (!*stream)
  521. {
  522. *stream = stream_new(stream_size);
  523. }
  524. else
  525. {
  526. if (STREAM_SIZE(*stream) != stream_size)
  527. stream_resize(*stream, stream_size);
  528. stream_reset(*stream);
  529. }
  530. }
  531. int
  532. isis_circuit_up (struct isis_circuit *circuit)
  533. {
  534. int retv;
  535. /* Set the flags for all the lsps of the circuit. */
  536. isis_circuit_update_all_srmflags (circuit, 1);
  537. if (circuit->state == C_STATE_UP)
  538. return ISIS_OK;
  539. if (circuit->is_passive)
  540. return ISIS_OK;
  541. if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit))
  542. {
  543. zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
  544. isis_circuit_pdu_size(circuit), circuit->interface->name,
  545. circuit->area->lsp_mtu);
  546. isis_circuit_update_all_srmflags(circuit, 0);
  547. return ISIS_ERROR;
  548. }
  549. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  550. {
  551. /*
  552. * Get the Hardware Address
  553. */
  554. if (circuit->interface->hw_addr_len != ETH_ALEN)
  555. {
  556. zlog_warn ("unsupported link layer");
  557. }
  558. else
  559. {
  560. memcpy (circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN);
  561. }
  562. #ifdef EXTREME_DEGUG
  563. zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
  564. circuit->interface->ifindex, ISO_MTU (circuit),
  565. snpa_print (circuit->u.bc.snpa));
  566. #endif /* EXTREME_DEBUG */
  567. circuit->u.bc.adjdb[0] = list_new ();
  568. circuit->u.bc.adjdb[1] = list_new ();
  569. /*
  570. * ISO 10589 - 8.4.1 Enabling of broadcast circuits
  571. */
  572. /* initilizing the hello sending threads
  573. * for a broadcast IF
  574. */
  575. /* 8.4.1 a) commence sending of IIH PDUs */
  576. if (circuit->is_type & IS_LEVEL_1)
  577. {
  578. thread_add_event (master, send_lan_l1_hello, circuit, 0);
  579. circuit->u.bc.lan_neighs[0] = list_new ();
  580. }
  581. if (circuit->is_type & IS_LEVEL_2)
  582. {
  583. thread_add_event (master, send_lan_l2_hello, circuit, 0);
  584. circuit->u.bc.lan_neighs[1] = list_new ();
  585. }
  586. /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
  587. /* 8.4.1 c) FIXME: listen for ESH PDUs */
  588. /* 8.4.1 d) */
  589. /* dr election will commence in... */
  590. if (circuit->is_type & IS_LEVEL_1)
  591. THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1,
  592. circuit, 2 * circuit->hello_interval[0]);
  593. if (circuit->is_type & IS_LEVEL_2)
  594. THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2,
  595. circuit, 2 * circuit->hello_interval[1]);
  596. }
  597. else
  598. {
  599. /* initializing the hello send threads
  600. * for a ptp IF
  601. */
  602. circuit->u.p2p.neighbor = NULL;
  603. thread_add_event (master, send_p2p_hello, circuit, 0);
  604. }
  605. /* initializing PSNP timers */
  606. if (circuit->is_type & IS_LEVEL_1)
  607. THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
  608. isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
  609. if (circuit->is_type & IS_LEVEL_2)
  610. THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
  611. isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
  612. /* unified init for circuits; ignore warnings below this level */
  613. retv = isis_sock_init (circuit);
  614. if (retv != ISIS_OK)
  615. {
  616. isis_circuit_down (circuit);
  617. return retv;
  618. }
  619. /* initialize the circuit streams after opening connection */
  620. isis_circuit_stream(circuit, &circuit->rcv_stream);
  621. isis_circuit_stream(circuit, &circuit->snd_stream);
  622. #ifdef GNU_LINUX
  623. THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
  624. circuit->fd);
  625. #else
  626. THREAD_TIMER_ON (master, circuit->t_read, isis_receive, circuit,
  627. circuit->fd);
  628. #endif
  629. circuit->lsp_queue = list_new ();
  630. circuit->lsp_queue_last_cleared = time (NULL);
  631. return ISIS_OK;
  632. }
  633. void
  634. isis_circuit_down (struct isis_circuit *circuit)
  635. {
  636. if (circuit->state != C_STATE_UP)
  637. return;
  638. /* Clear the flags for all the lsps of the circuit. */
  639. isis_circuit_update_all_srmflags (circuit, 0);
  640. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  641. {
  642. /* destroy neighbour lists */
  643. if (circuit->u.bc.lan_neighs[0])
  644. {
  645. list_delete (circuit->u.bc.lan_neighs[0]);
  646. circuit->u.bc.lan_neighs[0] = NULL;
  647. }
  648. if (circuit->u.bc.lan_neighs[1])
  649. {
  650. list_delete (circuit->u.bc.lan_neighs[1]);
  651. circuit->u.bc.lan_neighs[1] = NULL;
  652. }
  653. /* destroy adjacency databases */
  654. if (circuit->u.bc.adjdb[0])
  655. {
  656. circuit->u.bc.adjdb[0]->del = isis_delete_adj;
  657. list_delete (circuit->u.bc.adjdb[0]);
  658. circuit->u.bc.adjdb[0] = NULL;
  659. }
  660. if (circuit->u.bc.adjdb[1])
  661. {
  662. circuit->u.bc.adjdb[1]->del = isis_delete_adj;
  663. list_delete (circuit->u.bc.adjdb[1]);
  664. circuit->u.bc.adjdb[1] = NULL;
  665. }
  666. if (circuit->u.bc.is_dr[0])
  667. {
  668. isis_dr_resign (circuit, 1);
  669. circuit->u.bc.is_dr[0] = 0;
  670. }
  671. memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1);
  672. if (circuit->u.bc.is_dr[1])
  673. {
  674. isis_dr_resign (circuit, 2);
  675. circuit->u.bc.is_dr[1] = 0;
  676. }
  677. memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1);
  678. memset (circuit->u.bc.snpa, 0, ETH_ALEN);
  679. THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]);
  680. THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]);
  681. THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
  682. THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
  683. THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[0]);
  684. THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[1]);
  685. circuit->lsp_regenerate_pending[0] = 0;
  686. circuit->lsp_regenerate_pending[1] = 0;
  687. }
  688. else if (circuit->circ_type == CIRCUIT_T_P2P)
  689. {
  690. isis_delete_adj (circuit->u.p2p.neighbor);
  691. circuit->u.p2p.neighbor = NULL;
  692. THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
  693. }
  694. /* Cancel all active threads */
  695. THREAD_TIMER_OFF (circuit->t_send_csnp[0]);
  696. THREAD_TIMER_OFF (circuit->t_send_csnp[1]);
  697. THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
  698. THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
  699. THREAD_OFF (circuit->t_read);
  700. if (circuit->lsp_queue)
  701. {
  702. circuit->lsp_queue->del = NULL;
  703. list_delete (circuit->lsp_queue);
  704. circuit->lsp_queue = NULL;
  705. }
  706. /* send one gratuitous hello to spead up convergence */
  707. if (circuit->is_type & IS_LEVEL_1)
  708. send_hello (circuit, IS_LEVEL_1);
  709. if (circuit->is_type & IS_LEVEL_2)
  710. send_hello (circuit, IS_LEVEL_2);
  711. circuit->upadjcount[0] = 0;
  712. circuit->upadjcount[1] = 0;
  713. /* close the socket */
  714. if (circuit->fd)
  715. {
  716. close (circuit->fd);
  717. circuit->fd = 0;
  718. }
  719. if (circuit->rcv_stream != NULL)
  720. {
  721. stream_free (circuit->rcv_stream);
  722. circuit->rcv_stream = NULL;
  723. }
  724. if (circuit->snd_stream != NULL)
  725. {
  726. stream_free (circuit->snd_stream);
  727. circuit->snd_stream = NULL;
  728. }
  729. thread_cancel_event (master, circuit);
  730. return;
  731. }
  732. void
  733. circuit_update_nlpids (struct isis_circuit *circuit)
  734. {
  735. circuit->nlpids.count = 0;
  736. if (circuit->ip_router)
  737. {
  738. circuit->nlpids.nlpids[0] = NLPID_IP;
  739. circuit->nlpids.count++;
  740. }
  741. #ifdef HAVE_IPV6
  742. if (circuit->ipv6_router)
  743. {
  744. circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
  745. circuit->nlpids.count++;
  746. }
  747. #endif /* HAVE_IPV6 */
  748. return;
  749. }
  750. void
  751. isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
  752. char detail)
  753. {
  754. if (detail == ISIS_UI_LEVEL_BRIEF)
  755. {
  756. vty_out (vty, " %-12s", circuit->interface->name);
  757. vty_out (vty, "0x%-7x", circuit->circuit_id);
  758. vty_out (vty, "%-9s", circuit_state2string (circuit->state));
  759. vty_out (vty, "%-9s", circuit_type2string (circuit->circ_type));
  760. vty_out (vty, "%-9s", circuit_t2string (circuit->is_type));
  761. vty_out (vty, "%s", VTY_NEWLINE);
  762. }
  763. if (detail == ISIS_UI_LEVEL_DETAIL)
  764. {
  765. struct listnode *node;
  766. struct prefix *ip_addr;
  767. u_char buf[BUFSIZ];
  768. vty_out (vty, " Interface: %s", circuit->interface->name);
  769. vty_out (vty, ", State: %s", circuit_state2string (circuit->state));
  770. if (circuit->is_passive)
  771. vty_out (vty, ", Passive");
  772. else
  773. vty_out (vty, ", Active");
  774. vty_out (vty, ", Circuit Id: 0x%x", circuit->circuit_id);
  775. vty_out (vty, "%s", VTY_NEWLINE);
  776. vty_out (vty, " Type: %s", circuit_type2string (circuit->circ_type));
  777. vty_out (vty, ", Level: %s", circuit_t2string (circuit->is_type));
  778. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  779. vty_out (vty, ", SNPA: %-10s", snpa_print (circuit->u.bc.snpa));
  780. vty_out (vty, "%s", VTY_NEWLINE);
  781. if (circuit->is_type & IS_LEVEL_1)
  782. {
  783. vty_out (vty, " Level-1 Information:%s", VTY_NEWLINE);
  784. if (circuit->area->newmetric)
  785. vty_out (vty, " Metric: %d", circuit->te_metric[0]);
  786. else
  787. vty_out (vty, " Metric: %d",
  788. circuit->metric[0]);
  789. if (!circuit->is_passive)
  790. {
  791. vty_out (vty, ", Active neighbors: %u%s",
  792. circuit->upadjcount[0], VTY_NEWLINE);
  793. vty_out (vty, " Hello interval: %u, "
  794. "Holddown count: %u %s%s",
  795. circuit->hello_interval[0],
  796. circuit->hello_multiplier[0],
  797. (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
  798. VTY_NEWLINE);
  799. vty_out (vty, " CNSP interval: %u, "
  800. "PSNP interval: %u%s",
  801. circuit->csnp_interval[0],
  802. circuit->psnp_interval[0], VTY_NEWLINE);
  803. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  804. vty_out (vty, " LAN Priority: %u, %s%s",
  805. circuit->priority[0],
  806. (circuit->u.bc.is_dr[0] ? \
  807. "is DIS" : "is not DIS"), VTY_NEWLINE);
  808. }
  809. else
  810. {
  811. vty_out (vty, "%s", VTY_NEWLINE);
  812. }
  813. }
  814. if (circuit->is_type & IS_LEVEL_2)
  815. {
  816. vty_out (vty, " Level-2 Information:%s", VTY_NEWLINE);
  817. if (circuit->area->newmetric)
  818. vty_out (vty, " Metric: %d", circuit->te_metric[1]);
  819. else
  820. vty_out (vty, " Metric: %d",
  821. circuit->metric[1]);
  822. if (!circuit->is_passive)
  823. {
  824. vty_out (vty, ", Active neighbors: %u%s",
  825. circuit->upadjcount[1], VTY_NEWLINE);
  826. vty_out (vty, " Hello interval: %u, "
  827. "Holddown count: %u %s%s",
  828. circuit->hello_interval[1],
  829. circuit->hello_multiplier[1],
  830. (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
  831. VTY_NEWLINE);
  832. vty_out (vty, " CNSP interval: %u, "
  833. "PSNP interval: %u%s",
  834. circuit->csnp_interval[1],
  835. circuit->psnp_interval[1], VTY_NEWLINE);
  836. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  837. vty_out (vty, " LAN Priority: %u, %s%s",
  838. circuit->priority[1],
  839. (circuit->u.bc.is_dr[1] ? \
  840. "is DIS" : "is not DIS"), VTY_NEWLINE);
  841. }
  842. else
  843. {
  844. vty_out (vty, "%s", VTY_NEWLINE);
  845. }
  846. }
  847. if (circuit->ip_addrs && listcount (circuit->ip_addrs) > 0)
  848. {
  849. vty_out (vty, " IP Prefix(es):%s", VTY_NEWLINE);
  850. for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip_addr))
  851. {
  852. prefix2str (ip_addr, (char*)buf, BUFSIZ),
  853. vty_out (vty, " %s%s", buf, VTY_NEWLINE);
  854. }
  855. }
  856. if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0)
  857. {
  858. vty_out(vty, " IPv6 Link-Locals:%s", VTY_NEWLINE);
  859. for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip_addr))
  860. {
  861. prefix2str(ip_addr, (char*)buf, BUFSIZ),
  862. vty_out(vty, " %s%s", buf, VTY_NEWLINE);
  863. }
  864. }
  865. if (circuit->ipv6_non_link && listcount(circuit->ipv6_non_link) > 0)
  866. {
  867. vty_out(vty, " IPv6 Prefixes:%s", VTY_NEWLINE);
  868. for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip_addr))
  869. {
  870. prefix2str(ip_addr, (char*)buf, BUFSIZ),
  871. vty_out(vty, " %s%s", buf, VTY_NEWLINE);
  872. }
  873. }
  874. vty_out (vty, "%s", VTY_NEWLINE);
  875. }
  876. return;
  877. }
  878. int
  879. isis_interface_config_write (struct vty *vty)
  880. {
  881. int write = 0;
  882. struct listnode *node, *node2;
  883. struct interface *ifp;
  884. struct isis_area *area;
  885. struct isis_circuit *circuit;
  886. int i;
  887. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  888. {
  889. /* IF name */
  890. vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE);
  891. write++;
  892. /* IF desc */
  893. if (ifp->desc)
  894. {
  895. vty_out (vty, " description %s%s", ifp->desc, VTY_NEWLINE);
  896. write++;
  897. }
  898. /* ISIS Circuit */
  899. for (ALL_LIST_ELEMENTS_RO (isis->area_list, node2, area))
  900. {
  901. circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
  902. if (circuit == NULL)
  903. continue;
  904. if (circuit->ip_router)
  905. {
  906. vty_out (vty, " ip router isis %s%s", area->area_tag,
  907. VTY_NEWLINE);
  908. write++;
  909. }
  910. if (circuit->is_passive)
  911. {
  912. vty_out (vty, " isis passive%s", VTY_NEWLINE);
  913. write++;
  914. }
  915. if (circuit->circ_type_config == CIRCUIT_T_P2P)
  916. {
  917. vty_out (vty, " isis network point-to-point%s", VTY_NEWLINE);
  918. write++;
  919. }
  920. #ifdef HAVE_IPV6
  921. if (circuit->ipv6_router)
  922. {
  923. vty_out (vty, " ipv6 router isis %s%s", area->area_tag,
  924. VTY_NEWLINE);
  925. write++;
  926. }
  927. #endif /* HAVE_IPV6 */
  928. /* ISIS - circuit type */
  929. if (circuit->is_type == IS_LEVEL_1)
  930. {
  931. vty_out (vty, " isis circuit-type level-1%s", VTY_NEWLINE);
  932. write++;
  933. }
  934. else
  935. {
  936. if (circuit->is_type == IS_LEVEL_2)
  937. {
  938. vty_out (vty, " isis circuit-type level-2-only%s",
  939. VTY_NEWLINE);
  940. write++;
  941. }
  942. }
  943. /* ISIS - CSNP interval */
  944. if (circuit->csnp_interval[0] == circuit->csnp_interval[1])
  945. {
  946. if (circuit->csnp_interval[0] != DEFAULT_CSNP_INTERVAL)
  947. {
  948. vty_out (vty, " isis csnp-interval %d%s",
  949. circuit->csnp_interval[0], VTY_NEWLINE);
  950. write++;
  951. }
  952. }
  953. else
  954. {
  955. for (i = 0; i < 2; i++)
  956. {
  957. if (circuit->csnp_interval[i] != DEFAULT_CSNP_INTERVAL)
  958. {
  959. vty_out (vty, " isis csnp-interval %d level-%d%s",
  960. circuit->csnp_interval[i], i + 1, VTY_NEWLINE);
  961. write++;
  962. }
  963. }
  964. }
  965. /* ISIS - PSNP interval */
  966. if (circuit->psnp_interval[0] == circuit->psnp_interval[1])
  967. {
  968. if (circuit->psnp_interval[0] != DEFAULT_PSNP_INTERVAL)
  969. {
  970. vty_out (vty, " isis psnp-interval %d%s",
  971. circuit->psnp_interval[0], VTY_NEWLINE);
  972. write++;
  973. }
  974. }
  975. else
  976. {
  977. for (i = 0; i < 2; i++)
  978. {
  979. if (circuit->psnp_interval[i] != DEFAULT_PSNP_INTERVAL)
  980. {
  981. vty_out (vty, " isis psnp-interval %d level-%d%s",
  982. circuit->psnp_interval[i], i + 1, VTY_NEWLINE);
  983. write++;
  984. }
  985. }
  986. }
  987. /* ISIS - Hello padding - Defaults to true so only display if false */
  988. if (circuit->pad_hellos == 0)
  989. {
  990. vty_out (vty, " no isis hello padding%s", VTY_NEWLINE);
  991. write++;
  992. }
  993. /* ISIS - Hello interval */
  994. if (circuit->hello_interval[0] == circuit->hello_interval[1])
  995. {
  996. if (circuit->hello_interval[0] != DEFAULT_HELLO_INTERVAL)
  997. {
  998. vty_out (vty, " isis hello-interval %d%s",
  999. circuit->hello_interval[0], VTY_NEWLINE);
  1000. write++;
  1001. }
  1002. }
  1003. else
  1004. {
  1005. for (i = 0; i < 2; i++)
  1006. {
  1007. if (circuit->hello_interval[i] != DEFAULT_HELLO_INTERVAL)
  1008. {
  1009. vty_out (vty, " isis hello-interval %d level-%d%s",
  1010. circuit->hello_interval[i], i + 1, VTY_NEWLINE);
  1011. write++;
  1012. }
  1013. }
  1014. }
  1015. /* ISIS - Hello Multiplier */
  1016. if (circuit->hello_multiplier[0] == circuit->hello_multiplier[1])
  1017. {
  1018. if (circuit->hello_multiplier[0] != DEFAULT_HELLO_MULTIPLIER)
  1019. {
  1020. vty_out (vty, " isis hello-multiplier %d%s",
  1021. circuit->hello_multiplier[0], VTY_NEWLINE);
  1022. write++;
  1023. }
  1024. }
  1025. else
  1026. {
  1027. for (i = 0; i < 2; i++)
  1028. {
  1029. if (circuit->hello_multiplier[i] != DEFAULT_HELLO_MULTIPLIER)
  1030. {
  1031. vty_out (vty, " isis hello-multiplier %d level-%d%s",
  1032. circuit->hello_multiplier[i], i + 1,
  1033. VTY_NEWLINE);
  1034. write++;
  1035. }
  1036. }
  1037. }
  1038. /* ISIS - Priority */
  1039. if (circuit->priority[0] == circuit->priority[1])
  1040. {
  1041. if (circuit->priority[0] != DEFAULT_PRIORITY)
  1042. {
  1043. vty_out (vty, " isis priority %d%s",
  1044. circuit->priority[0], VTY_NEWLINE);
  1045. write++;
  1046. }
  1047. }
  1048. else
  1049. {
  1050. for (i = 0; i < 2; i++)
  1051. {
  1052. if (circuit->priority[i] != DEFAULT_PRIORITY)
  1053. {
  1054. vty_out (vty, " isis priority %d level-%d%s",
  1055. circuit->priority[i], i + 1, VTY_NEWLINE);
  1056. write++;
  1057. }
  1058. }
  1059. }
  1060. /* ISIS - Metric */
  1061. if (circuit->te_metric[0] == circuit->te_metric[1])
  1062. {
  1063. if (circuit->te_metric[0] != DEFAULT_CIRCUIT_METRIC)
  1064. {
  1065. vty_out (vty, " isis metric %d%s", circuit->te_metric[0],
  1066. VTY_NEWLINE);
  1067. write++;
  1068. }
  1069. }
  1070. else
  1071. {
  1072. for (i = 0; i < 2; i++)
  1073. {
  1074. if (circuit->te_metric[i] != DEFAULT_CIRCUIT_METRIC)
  1075. {
  1076. vty_out (vty, " isis metric %d level-%d%s",
  1077. circuit->te_metric[i], i + 1, VTY_NEWLINE);
  1078. write++;
  1079. }
  1080. }
  1081. }
  1082. if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5)
  1083. {
  1084. vty_out (vty, " isis password md5 %s%s", circuit->passwd.passwd,
  1085. VTY_NEWLINE);
  1086. write++;
  1087. }
  1088. else if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT)
  1089. {
  1090. vty_out (vty, " isis password clear %s%s", circuit->passwd.passwd,
  1091. VTY_NEWLINE);
  1092. write++;
  1093. }
  1094. }
  1095. vty_out (vty, "!%s", VTY_NEWLINE);
  1096. }
  1097. return write;
  1098. }
  1099. struct isis_circuit *
  1100. isis_circuit_create (struct isis_area *area, struct interface *ifp)
  1101. {
  1102. struct isis_circuit *circuit = circuit_scan_by_ifp (ifp);
  1103. if (circuit && circuit->area)
  1104. return NULL;
  1105. circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area);
  1106. if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
  1107. return circuit;
  1108. isis_circuit_if_bind (circuit, ifp);
  1109. return circuit;
  1110. }
  1111. void
  1112. isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router)
  1113. {
  1114. struct isis_area *area = circuit->area;
  1115. bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router;
  1116. bool was_enabled = !!circuit->area;
  1117. area->ip_circuits += ip_router - circuit->ip_router;
  1118. area->ipv6_circuits += ipv6_router - circuit->ipv6_router;
  1119. circuit->ip_router = ip_router;
  1120. circuit->ipv6_router = ipv6_router;
  1121. if (!change)
  1122. return;
  1123. circuit_update_nlpids (circuit);
  1124. if (!ip_router && !ipv6_router)
  1125. isis_csm_state_change (ISIS_DISABLE, circuit, area);
  1126. else if (!was_enabled)
  1127. isis_csm_state_change (ISIS_ENABLE, circuit, area);
  1128. else
  1129. lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
  1130. }
  1131. int
  1132. isis_circuit_passive_set (struct isis_circuit *circuit, bool passive)
  1133. {
  1134. if (circuit->is_passive == passive)
  1135. return 0;
  1136. if (if_is_loopback (circuit->interface) && !passive)
  1137. return -1;
  1138. if (circuit->state != C_STATE_UP)
  1139. {
  1140. circuit->is_passive = passive;
  1141. }
  1142. else
  1143. {
  1144. struct isis_area *area = circuit->area;
  1145. isis_csm_state_change (ISIS_DISABLE, circuit, area);
  1146. circuit->is_passive = passive;
  1147. isis_csm_state_change (ISIS_ENABLE, circuit, area);
  1148. }
  1149. return 0;
  1150. }
  1151. int
  1152. isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric)
  1153. {
  1154. assert (level == IS_LEVEL_1 || level == IS_LEVEL_2);
  1155. if (metric > MAX_WIDE_LINK_METRIC)
  1156. return -1;
  1157. if (circuit->area && circuit->area->oldmetric
  1158. && metric > MAX_NARROW_LINK_METRIC)
  1159. return -1;
  1160. circuit->te_metric[level - 1] = metric;
  1161. circuit->metric[level - 1] = metric;
  1162. if (circuit->area)
  1163. lsp_regenerate_schedule (circuit->area, level, 0);
  1164. return 0;
  1165. }
  1166. int
  1167. isis_circuit_passwd_unset (struct isis_circuit *circuit)
  1168. {
  1169. memset(&circuit->passwd, 0, sizeof(circuit->passwd));
  1170. return 0;
  1171. }
  1172. static int
  1173. isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd)
  1174. {
  1175. int len;
  1176. if (!passwd)
  1177. return -1;
  1178. len = strlen(passwd);
  1179. if (len > 254)
  1180. return -1;
  1181. circuit->passwd.len = len;
  1182. strncpy((char *)circuit->passwd.passwd, passwd, 255);
  1183. circuit->passwd.type = passwd_type;
  1184. return 0;
  1185. }
  1186. int
  1187. isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd)
  1188. {
  1189. return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd);
  1190. }
  1191. int
  1192. isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd)
  1193. {
  1194. return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd);
  1195. }
  1196. struct cmd_node interface_node = {
  1197. INTERFACE_NODE,
  1198. "%s(config-if)# ",
  1199. 1,
  1200. };
  1201. int
  1202. isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type)
  1203. {
  1204. /* Changing the network type to/of loopback or unknown interfaces
  1205. * is not supported. */
  1206. if (circ_type == CIRCUIT_T_UNKNOWN
  1207. || circ_type == CIRCUIT_T_LOOPBACK
  1208. || circuit->circ_type == CIRCUIT_T_LOOPBACK)
  1209. {
  1210. if (circuit->circ_type != circ_type)
  1211. return -1;
  1212. else
  1213. return 0;
  1214. }
  1215. if (circuit->circ_type == circ_type)
  1216. return 0;
  1217. if (circuit->state != C_STATE_UP)
  1218. {
  1219. circuit->circ_type = circ_type;
  1220. circuit->circ_type_config = circ_type;
  1221. }
  1222. else
  1223. {
  1224. struct isis_area *area = circuit->area;
  1225. if (circ_type == CIRCUIT_T_BROADCAST
  1226. && !if_is_broadcast(circuit->interface))
  1227. return -1;
  1228. isis_csm_state_change(ISIS_DISABLE, circuit, area);
  1229. circuit->circ_type = circ_type;
  1230. circuit->circ_type_config = circ_type;
  1231. isis_csm_state_change(ISIS_ENABLE, circuit, area);
  1232. }
  1233. return 0;
  1234. }
  1235. int
  1236. isis_if_new_hook (struct interface *ifp)
  1237. {
  1238. return 0;
  1239. }
  1240. int
  1241. isis_if_delete_hook (struct interface *ifp)
  1242. {
  1243. struct isis_circuit *circuit;
  1244. /* Clean up the circuit data */
  1245. if (ifp && ifp->info)
  1246. {
  1247. circuit = ifp->info;
  1248. isis_csm_state_change (IF_DOWN_FROM_Z, circuit, circuit->area);
  1249. isis_csm_state_change (ISIS_DISABLE, circuit, circuit->area);
  1250. }
  1251. return 0;
  1252. }
  1253. void
  1254. isis_circuit_init ()
  1255. {
  1256. /* Initialize Zebra interface data structure */
  1257. if_add_hook (IF_NEW_HOOK, isis_if_new_hook);
  1258. if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook);
  1259. /* Install interface node */
  1260. install_node (&interface_node, isis_interface_config_write);
  1261. install_element (CONFIG_NODE, &interface_cmd);
  1262. install_element (CONFIG_NODE, &no_interface_cmd);
  1263. install_default (INTERFACE_NODE);
  1264. install_element (INTERFACE_NODE, &interface_desc_cmd);
  1265. install_element (INTERFACE_NODE, &no_interface_desc_cmd);
  1266. isis_vty_init ();
  1267. }