1 /*
2 * IS-IS Rout(e)ing protocol - isis_circuit.c
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
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #include "pmacct.h"
24 #include "isis.h"
25
26 #ifndef ETHER_ADDR_LEN
27 #define ETHER_ADDR_LEN ETHERADDRL
28 #endif
29
30 #include "thread.h"
31 #include "hash.h"
32 #include "prefix.h"
33 #include "stream.h"
34
35 #include "dict.h"
36 #include "iso.h"
37 #include "isis_constants.h"
38 #include "isis_common.h"
39 #include "isis_circuit.h"
40 #include "isis_tlv.h"
41 #include "isis_lsp.h"
42 #include "isis_pdu.h"
43 #include "isis_network.h"
44 #include "isis_misc.h"
45 #include "isis_constants.h"
46 #include "isis_adjacency.h"
47 #include "isis_flags.h"
48 #include "isisd.h"
49 #include "isis_csm.h"
50 #include "isis_events.h"
51
52 extern struct thread_master *master;
53 extern struct isis *isis;
54
55 /*
56 * Prototypes.
57 */
58 void isis_circuit_down(struct isis_circuit *);
59
60 struct isis_circuit *
isis_circuit_new()61 isis_circuit_new ()
62 {
63 struct isis_circuit *circuit;
64 int i;
65
66 circuit = calloc(1, sizeof (struct isis_circuit));
67 if (circuit)
68 {
69 /* set default metrics for circuit */
70 for (i = 0; i < 2; i++)
71 {
72 circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRICS;
73 circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED;
74 circuit->metrics[i].metric_error = METRICS_UNSUPPORTED;
75 circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED;
76 circuit->te_metric[i] = DEFAULT_CIRCUIT_METRICS;
77 }
78 }
79 else
80 {
81 Log(LOG_ERR, "ERROR ( %s/core/ISIS ): Can't calloc isis circuit\n", config.name);
82 return NULL;
83 }
84
85 return circuit;
86 }
87
88 void
isis_circuit_configure(struct isis_circuit * circuit,struct isis_area * area)89 isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
90 {
91 int i;
92 circuit->area = area;
93 /*
94 * The level for the circuit is same as for the area, unless configured
95 * otherwise.
96 */
97 circuit->circuit_is_type = area->is_type;
98 /*
99 * Default values
100 */
101 for (i = 0; i < 2; i++)
102 {
103 circuit->hello_interval[i] = HELLO_INTERVAL;
104 circuit->hello_multiplier[i] = HELLO_MULTIPLIER;
105 circuit->csnp_interval[i] = CSNP_INTERVAL;
106 circuit->psnp_interval[i] = PSNP_INTERVAL;
107 circuit->u.bc.priority[i] = DEFAULT_PRIORITY;
108 }
109 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
110 {
111 circuit->u.bc.adjdb[0] = pm_list_new ();
112 circuit->u.bc.adjdb[1] = pm_list_new ();
113 circuit->u.bc.pad_hellos = 1;
114 }
115 circuit->lsp_interval = LSP_INTERVAL;
116
117 /*
118 * Add the circuit into area
119 */
120 pm_listnode_add (area->circuit_list, circuit);
121
122 circuit->idx = flags_get_index (&area->flags);
123 circuit->lsp_queue = pm_list_new ();
124
125 return;
126 }
127
128 void
isis_circuit_deconfigure(struct isis_circuit * circuit,struct isis_area * area)129 isis_circuit_deconfigure (struct isis_circuit *circuit,
130 struct isis_area *area)
131 {
132
133 /* destroy adjacencies */
134 if (circuit->u.bc.adjdb[0])
135 isis_adjdb_iterate (circuit->u.bc.adjdb[0], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[0]);
136 if (circuit->u.bc.adjdb[1])
137 isis_adjdb_iterate (circuit->u.bc.adjdb[1], (void(*) (struct isis_adjacency *, void *)) isis_delete_adj, circuit->u.bc.adjdb[1]);
138 /* Remove circuit from area */
139 pm_listnode_delete (area->circuit_list, circuit);
140 /* Free the index of SRM and SSN flags */
141 flags_free_index (&area->flags, circuit->idx);
142
143 return;
144 }
145
146 void
isis_circuit_del(struct isis_circuit * circuit)147 isis_circuit_del (struct isis_circuit *circuit)
148 {
149
150 if (!circuit)
151 return;
152
153 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
154 {
155 /* destroy adjacency databases */
156 if (circuit->u.bc.adjdb[0])
157 pm_list_delete (circuit->u.bc.adjdb[0]);
158 if (circuit->u.bc.adjdb[1])
159 pm_list_delete (circuit->u.bc.adjdb[1]);
160 /* destroy neighbour lists */
161 if (circuit->u.bc.lan_neighs[0])
162 pm_list_delete (circuit->u.bc.lan_neighs[0]);
163 if (circuit->u.bc.lan_neighs[1])
164 pm_list_delete (circuit->u.bc.lan_neighs[1]);
165 /* destroy addresses */
166 }
167 if (circuit->ip_addrs)
168 pm_list_delete (circuit->ip_addrs);
169 if (circuit->ipv6_link)
170 pm_list_delete (circuit->ipv6_link);
171 if (circuit->ipv6_non_link)
172 pm_list_delete (circuit->ipv6_non_link);
173
174 /* and lastly the circuit itself */
175 free(circuit);
176
177 return;
178 }
179
180 void
isis_circuit_up(struct isis_circuit * circuit)181 isis_circuit_up (struct isis_circuit *circuit)
182 {
183 if (circuit->circ_type == CIRCUIT_T_P2P)
184 {
185 /* initializing the hello send threads
186 * for a ptp IF
187 */
188 thread_add_event (master, send_p2p_hello, circuit, 0);
189 }
190
191 /* if needed, initialize the circuit streams (most likely not) */
192 if (circuit->rcv_stream == NULL)
193 circuit->rcv_stream = stream_new (ISO_MTU (circuit));
194
195 if (circuit->snd_stream == NULL)
196 circuit->snd_stream = stream_new (ISO_MTU (circuit));
197
198 // isis_sock_init (circuit);
199
200 // THREAD_TIMER_ON (master, circuit->t_read, isis_receive, circuit, circuit->fd);
201 }
202
203 void
isis_circuit_down(struct isis_circuit * circuit)204 isis_circuit_down (struct isis_circuit *circuit)
205 {
206 /* Cancel all active threads -- FIXME: wrong place */
207 /* HT: Read thread if GNU_LINUX, TIMER thread otherwise. */
208 THREAD_OFF (circuit->t_read);
209 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
210 {
211 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]);
212 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]);
213 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
214 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
215 }
216 else if (circuit->circ_type == CIRCUIT_T_P2P)
217 {
218 THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
219 }
220
221 if (circuit->t_send_psnp[0]) {
222 THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
223 }
224 if (circuit->t_send_psnp[1]) {
225 THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
226 }
227 /* close the socket */
228 close (circuit->fd);
229
230 return;
231 }
232
233 void
circuit_update_nlpids(struct isis_circuit * circuit)234 circuit_update_nlpids (struct isis_circuit *circuit)
235 {
236 circuit->nlpids.count = 0;
237
238 if (circuit->ip_router)
239 {
240 circuit->nlpids.nlpids[0] = NLPID_IP;
241 circuit->nlpids.count++;
242 }
243 if (circuit->ipv6_router)
244 {
245 circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
246 circuit->nlpids.count++;
247 }
248 return;
249 }
250