]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * EIGRP Interface Functions. | |
3 | * Copyright (C) 2013-2016 | |
4 | * Authors: | |
5 | * Donnie Savage | |
6 | * Jan Janovic | |
7 | * Matej Perina | |
8 | * Peter Orsag | |
9 | * Peter Paluch | |
10 | * Frantisek Gazo | |
11 | * Tomas Hvorkovy | |
12 | * Martin Kontsek | |
13 | * Lukas Koribsky | |
14 | * | |
15 | * This file is part of GNU Zebra. | |
16 | * | |
17 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
18 | * under the terms of the GNU General Public License as published by the | |
19 | * Free Software Foundation; either version 2, or (at your option) any | |
20 | * later version. | |
21 | * | |
22 | * GNU Zebra is distributed in the hope that it will be useful, but | |
23 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
25 | * General Public License for more details. | |
26 | * | |
27 | * You should have received a copy of the GNU General Public License | |
28 | * along with GNU Zebra; see the file COPYING. If not, write to the Free | |
29 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
30 | * 02111-1307, USA. | |
31 | */ | |
32 | ||
33 | #include <zebra.h> | |
34 | ||
35 | #include "thread.h" | |
36 | #include "linklist.h" | |
37 | #include "prefix.h" | |
38 | #include "if.h" | |
39 | #include "table.h" | |
40 | #include "memory.h" | |
41 | #include "command.h" | |
42 | #include "stream.h" | |
43 | #include "log.h" | |
44 | #include "keychain.h" | |
45 | #include "vrf.h" | |
46 | ||
47 | #include "eigrpd/eigrp_structs.h" | |
48 | #include "eigrpd/eigrpd.h" | |
49 | #include "eigrpd/eigrp_interface.h" | |
50 | #include "eigrpd/eigrp_neighbor.h" | |
51 | #include "eigrpd/eigrp_packet.h" | |
52 | #include "eigrpd/eigrp_zebra.h" | |
53 | #include "eigrpd/eigrp_vty.h" | |
54 | #include "eigrpd/eigrp_network.h" | |
55 | #include "eigrpd/eigrp_topology.h" | |
56 | #include "eigrpd/eigrp_memory.h" | |
57 | ||
58 | static void | |
59 | eigrp_delete_from_if (struct interface *, struct eigrp_interface *); | |
60 | ||
61 | static void | |
62 | eigrp_add_to_if (struct interface *ifp, struct eigrp_interface *ei) | |
63 | { | |
64 | struct route_node *rn; | |
65 | struct prefix p; | |
66 | ||
67 | p = *ei->address; | |
68 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
69 | ||
70 | rn = route_node_get (IF_OIFS (ifp), &p); | |
71 | /* rn->info should either be NULL or equal to this ei | |
72 | * as route_node_get may return an existing node | |
73 | */ | |
74 | assert (!rn->info || rn->info == ei); | |
75 | rn->info = ei; | |
76 | } | |
77 | ||
78 | struct eigrp_interface * | |
79 | eigrp_if_new (struct eigrp *eigrp, struct interface *ifp, struct prefix *p) | |
80 | { | |
81 | struct eigrp_interface *ei; | |
82 | int i; | |
83 | ||
84 | if ((ei = eigrp_if_table_lookup (ifp, p)) == NULL) | |
85 | { | |
86 | ei = XCALLOC (MTYPE_EIGRP_IF, sizeof (struct eigrp_interface)); | |
87 | memset (ei, 0, sizeof (struct eigrp_interface)); | |
88 | } | |
89 | else | |
90 | return ei; | |
91 | ||
92 | /* Set zebra interface pointer. */ | |
93 | ei->ifp = ifp; | |
94 | ei->address = p; | |
95 | ||
96 | eigrp_add_to_if (ifp, ei); | |
97 | listnode_add (eigrp->eiflist, ei); | |
98 | ||
99 | ei->type = EIGRP_IFTYPE_BROADCAST; | |
100 | ||
101 | /* Initialize neighbor list. */ | |
102 | ei->nbrs = list_new (); | |
103 | ||
104 | ei->crypt_seqnum = time (NULL); | |
105 | ||
106 | /* Initialize lists */ | |
107 | for (i = 0; i < EIGRP_FILTER_MAX; i++) | |
108 | { | |
109 | ei->list[i] = NULL; | |
110 | ei->prefix[i] = NULL; | |
111 | ei->routemap[i] = NULL; | |
112 | } | |
113 | ||
114 | return ei; | |
115 | } | |
116 | ||
117 | /* lookup ei for specified prefix/ifp */ | |
118 | struct eigrp_interface * | |
119 | eigrp_if_table_lookup (struct interface *ifp, struct prefix *prefix) | |
120 | { | |
121 | struct prefix p; | |
122 | struct route_node *rn; | |
123 | struct eigrp_interface *rninfo = NULL; | |
124 | ||
125 | p = *prefix; | |
126 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
127 | ||
128 | /* route_node_get implicitly locks */ | |
129 | if ((rn = route_node_lookup (IF_OIFS (ifp), &p))) | |
130 | { | |
131 | rninfo = (struct eigrp_interface *) rn->info; | |
132 | route_unlock_node (rn); | |
133 | } | |
134 | ||
135 | return rninfo; | |
136 | } | |
137 | ||
138 | int | |
139 | eigrp_if_delete_hook (struct interface *ifp) | |
140 | { | |
141 | ||
142 | struct route_node *rn; | |
143 | ||
144 | route_table_finish (IF_OIFS (ifp)); | |
145 | ||
146 | for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn)) | |
147 | if (rn->info) | |
148 | eigrp_del_if_params (rn->info); | |
149 | route_table_finish (IF_OIFS_PARAMS (ifp)); | |
150 | ||
151 | XFREE (MTYPE_EIGRP_IF_INFO, ifp->info); | |
152 | ifp->info = NULL; | |
153 | ||
154 | return 0; | |
155 | } | |
156 | ||
157 | struct list *eigrp_iflist; | |
158 | ||
159 | void | |
160 | eigrp_if_init () | |
161 | { | |
162 | /* Initialize Zebra interface data structure. */ | |
163 | if_add_hook (IF_NEW_HOOK, eigrp_if_new_hook); | |
164 | if_add_hook (IF_DELETE_HOOK, eigrp_if_delete_hook); | |
165 | } | |
166 | ||
167 | int | |
168 | eigrp_if_new_hook (struct interface *ifp) | |
169 | { | |
170 | int rc = 0; | |
171 | ||
172 | ifp->info = XCALLOC (MTYPE_EIGRP_IF_INFO, sizeof (struct eigrp_if_info)); | |
173 | ||
174 | IF_OIFS (ifp) = route_table_init (); | |
175 | IF_OIFS_PARAMS (ifp) = route_table_init (); | |
176 | ||
177 | IF_DEF_PARAMS (ifp) = eigrp_new_if_params (); | |
178 | ||
179 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello); | |
180 | IF_DEF_PARAMS (ifp)->v_hello = (u_int32_t) EIGRP_HELLO_INTERVAL_DEFAULT; | |
181 | ||
182 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait); | |
183 | IF_DEF_PARAMS (ifp)->v_wait = (u_int16_t) EIGRP_HOLD_INTERVAL_DEFAULT; | |
184 | ||
185 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), bandwidth); | |
186 | IF_DEF_PARAMS (ifp)->bandwidth = (u_int32_t) EIGRP_BANDWIDTH_DEFAULT; | |
187 | ||
188 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), delay); | |
189 | IF_DEF_PARAMS (ifp)->delay = (u_int32_t) EIGRP_DELAY_DEFAULT; | |
190 | ||
191 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), reliability); | |
192 | IF_DEF_PARAMS (ifp)->reliability = (u_char) EIGRP_RELIABILITY_DEFAULT; | |
193 | ||
194 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), load); | |
195 | IF_DEF_PARAMS (ifp)->load = (u_char) EIGRP_LOAD_DEFAULT; | |
196 | ||
197 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type); | |
198 | IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_NONE; | |
199 | ||
200 | SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_keychain); | |
201 | IF_DEF_PARAMS (ifp)->auth_keychain= NULL; | |
202 | ||
203 | return rc; | |
204 | } | |
205 | ||
206 | struct eigrp_if_params * | |
207 | eigrp_new_if_params (void) | |
208 | { | |
209 | struct eigrp_if_params *eip; | |
210 | ||
211 | eip = XCALLOC (MTYPE_EIGRP_IF_PARAMS, sizeof (struct eigrp_if_params)); | |
212 | if (!eip) | |
213 | return NULL; | |
214 | ||
215 | UNSET_IF_PARAM (eip, passive_interface); | |
216 | UNSET_IF_PARAM (eip, v_hello); | |
217 | UNSET_IF_PARAM (eip, v_wait); | |
218 | UNSET_IF_PARAM (eip, bandwidth); | |
219 | UNSET_IF_PARAM (eip, delay); | |
220 | UNSET_IF_PARAM (eip, reliability); | |
221 | UNSET_IF_PARAM (eip, load); | |
222 | UNSET_IF_PARAM (eip, auth_keychain); | |
223 | UNSET_IF_PARAM (eip, auth_type); | |
224 | ||
225 | ||
226 | return eip; | |
227 | } | |
228 | ||
229 | void | |
230 | eigrp_del_if_params (struct eigrp_if_params *eip) | |
231 | { | |
232 | if(eip->auth_keychain) | |
233 | free(eip->auth_keychain); | |
234 | ||
235 | XFREE (MTYPE_EIGRP_IF_PARAMS, eip); | |
236 | } | |
237 | ||
238 | struct eigrp_if_params * | |
239 | eigrp_lookup_if_params (struct interface *ifp, struct in_addr addr) | |
240 | { | |
241 | struct prefix_ipv4 p; | |
242 | struct route_node *rn; | |
243 | ||
244 | p.family = AF_INET; | |
245 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
246 | p.prefix = addr; | |
247 | ||
248 | rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*) &p); | |
249 | ||
250 | if (rn) | |
251 | { | |
252 | route_unlock_node (rn); | |
253 | return rn->info; | |
254 | } | |
255 | ||
256 | return NULL; | |
257 | } | |
258 | ||
259 | int | |
260 | eigrp_if_up (struct eigrp_interface *ei) | |
261 | { | |
262 | struct eigrp_prefix_entry *pe; | |
263 | struct eigrp_neighbor_entry *ne; | |
264 | struct eigrp_metrics metric; | |
265 | struct eigrp_interface *ei2; | |
266 | struct listnode *node, *nnode; | |
267 | struct eigrp *eigrp = eigrp_lookup (); | |
268 | ||
269 | if (ei == NULL) | |
270 | return 0; | |
271 | ||
272 | if (eigrp != NULL) | |
273 | eigrp_adjust_sndbuflen (eigrp, ei->ifp->mtu); | |
274 | else | |
275 | zlog_warn ("%s: eigrp_lookup () returned NULL", __func__); | |
276 | eigrp_if_stream_set (ei); | |
277 | ||
278 | /* Set multicast memberships appropriately for new state. */ | |
279 | eigrp_if_set_multicast (ei); | |
280 | ||
281 | thread_add_event (master, eigrp_hello_timer, ei, (1)); | |
282 | ||
283 | /*Prepare metrics*/ | |
284 | metric.bandwith = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (ei,bandwidth)); | |
285 | metric.delay = eigrp_delay_to_scaled (EIGRP_IF_PARAM (ei,delay)); | |
286 | metric.load = EIGRP_IF_PARAM (ei,load); | |
287 | metric.reliability = EIGRP_IF_PARAM (ei,reliability); | |
288 | metric.mtu[0] = 0xDC; | |
289 | metric.mtu[1] = 0x05; | |
290 | metric.mtu[2] = 0x00; | |
291 | metric.hop_count = 0; | |
292 | metric.flags = 0; | |
293 | metric.tag = 0; | |
294 | ||
295 | /*Add connected entry to topology table*/ | |
296 | ||
297 | struct prefix_ipv4 *dest_addr = prefix_ipv4_new (); | |
298 | ||
299 | dest_addr->family = AF_INET; | |
300 | dest_addr->prefix = ei->connected->address->u.prefix4; | |
301 | dest_addr->prefixlen = ei->connected->address->prefixlen; | |
302 | apply_mask_ipv4 (dest_addr); | |
303 | pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, dest_addr); | |
304 | ||
305 | if (pe == NULL) | |
306 | { | |
307 | pe = eigrp_prefix_entry_new (); | |
308 | pe->serno = eigrp->serno; | |
309 | pe->destination_ipv4 = dest_addr; | |
310 | pe->af = AF_INET; | |
311 | pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED; | |
312 | ||
313 | pe->state = EIGRP_FSM_STATE_PASSIVE; | |
314 | pe->fdistance = eigrp_calculate_metrics (eigrp, &metric); | |
315 | pe->req_action |= EIGRP_FSM_NEED_UPDATE; | |
316 | eigrp_prefix_entry_add (eigrp->topology_table, pe); | |
317 | listnode_add(eigrp->topology_changes_internalIPV4, pe); | |
318 | } | |
319 | ne = eigrp_neighbor_entry_new (); | |
320 | ne->ei = ei; | |
321 | ne->reported_metric = metric; | |
322 | ne->total_metric = metric; | |
323 | ne->distance = eigrp_calculate_metrics (eigrp, &metric); | |
324 | ne->reported_distance = 0; | |
325 | ne->prefix = pe; | |
326 | ne->adv_router = eigrp->neighbor_self; | |
327 | ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG; | |
328 | eigrp_neighbor_entry_add (pe, ne); | |
329 | ||
330 | for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei2)) | |
331 | { | |
332 | if (ei2->nbrs->count != 0) | |
333 | { | |
334 | eigrp_update_send (ei2); | |
335 | } | |
336 | } | |
337 | ||
338 | pe->req_action &= ~EIGRP_FSM_NEED_UPDATE; | |
339 | listnode_delete(eigrp->topology_changes_internalIPV4, pe); | |
340 | ||
341 | return 1; | |
342 | } | |
343 | ||
344 | int | |
345 | eigrp_if_down (struct eigrp_interface *ei) | |
346 | { | |
347 | struct listnode *node, *nnode; | |
348 | struct eigrp_neighbor *nbr; | |
349 | ||
350 | if (ei == NULL) | |
351 | return 0; | |
352 | ||
353 | /* Shutdown packet reception and sending */ | |
354 | if(ei->t_hello) | |
355 | THREAD_OFF (ei->t_hello); | |
356 | ||
357 | eigrp_if_stream_unset (ei); | |
358 | ||
359 | /*Set infinite metrics to routes learned by this interface and start query process*/ | |
360 | for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr)) | |
361 | { | |
362 | eigrp_nbr_delete(nbr); | |
363 | } | |
364 | ||
365 | return 1; | |
366 | } | |
367 | ||
368 | void | |
369 | eigrp_if_stream_set (struct eigrp_interface *ei) | |
370 | { | |
371 | /* set output fifo queue. */ | |
372 | if (ei->obuf == NULL) | |
373 | ei->obuf = eigrp_fifo_new (); | |
374 | } | |
375 | ||
376 | void | |
377 | eigrp_if_stream_unset (struct eigrp_interface *ei) | |
378 | { | |
379 | struct eigrp *eigrp = ei->eigrp; | |
380 | ||
381 | if (ei->obuf) | |
382 | { | |
383 | eigrp_fifo_free (ei->obuf); | |
384 | ei->obuf = NULL; | |
385 | ||
386 | if (ei->on_write_q) | |
387 | { | |
388 | listnode_delete (eigrp->oi_write_q, ei); | |
389 | if (list_isempty (eigrp->oi_write_q)) | |
390 | thread_cancel (eigrp->t_write); | |
391 | ei->on_write_q = 0; | |
392 | } | |
393 | } | |
394 | } | |
395 | ||
396 | void | |
397 | eigrp_if_set_multicast (struct eigrp_interface *ei) | |
398 | { | |
399 | if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_ACTIVE)) | |
400 | { | |
401 | /* The interface should belong to the EIGRP-all-routers group. */ | |
402 | if (!EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS) | |
403 | && (eigrp_if_add_allspfrouters (ei->eigrp, ei->address, | |
404 | ei->ifp->ifindex) >= 0)) | |
405 | /* Set the flag only if the system call to join succeeded. */ | |
406 | EI_MEMBER_JOINED (ei, MEMBER_ALLROUTERS); | |
407 | } | |
408 | else | |
409 | { | |
410 | /* The interface should NOT belong to the EIGRP-all-routers group. */ | |
411 | if (EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS)) | |
412 | { | |
413 | /* Only actually drop if this is the last reference */ | |
414 | if (EI_MEMBER_COUNT (ei, MEMBER_ALLROUTERS) == 1) | |
415 | eigrp_if_drop_allspfrouters (ei->eigrp, ei->address, | |
416 | ei->ifp->ifindex); | |
417 | /* Unset the flag regardless of whether the system call to leave | |
418 | the group succeeded, since it's much safer to assume that | |
419 | we are not a member. */ | |
420 | EI_MEMBER_LEFT (ei, MEMBER_ALLROUTERS); | |
421 | } | |
422 | } | |
423 | } | |
424 | ||
425 | u_char | |
426 | eigrp_default_iftype (struct interface *ifp) | |
427 | { | |
428 | if (if_is_pointopoint (ifp)) | |
429 | return EIGRP_IFTYPE_POINTOPOINT; | |
430 | else if (if_is_loopback (ifp)) | |
431 | return EIGRP_IFTYPE_LOOPBACK; | |
432 | else | |
433 | return EIGRP_IFTYPE_BROADCAST; | |
434 | } | |
435 | ||
436 | void | |
437 | eigrp_if_free (struct eigrp_interface *ei, int source) | |
438 | { | |
439 | ||
440 | if (source == INTERFACE_DOWN_BY_VTY) | |
441 | { | |
442 | THREAD_OFF (ei->t_hello); | |
443 | eigrp_hello_send(ei,EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL); | |
444 | } | |
445 | ||
446 | eigrp_if_down (ei); | |
447 | ||
448 | list_delete (ei->nbrs); | |
449 | eigrp_delete_from_if (ei->ifp, ei); | |
450 | listnode_delete (ei->eigrp->eiflist, ei); | |
451 | ||
452 | thread_cancel_event (master, ei); | |
453 | ||
454 | memset (ei, 0, sizeof (*ei)); | |
455 | XFREE (MTYPE_EIGRP_IF, ei); | |
456 | } | |
457 | ||
458 | static void | |
459 | eigrp_delete_from_if (struct interface *ifp, struct eigrp_interface *ei) | |
460 | { | |
461 | struct route_node *rn; | |
462 | struct prefix p; | |
463 | ||
464 | p = *ei->address; | |
465 | p.prefixlen = IPV4_MAX_PREFIXLEN; | |
466 | ||
467 | rn = route_node_lookup (IF_OIFS (ei->ifp), &p); | |
468 | assert (rn); | |
469 | assert (rn->info); | |
470 | rn->info = NULL; | |
471 | route_unlock_node (rn); | |
472 | route_unlock_node (rn); | |
473 | } | |
474 | ||
475 | /* Simulate down/up on the interface. This is needed, for example, when | |
476 | the MTU changes. */ | |
477 | void | |
478 | eigrp_if_reset (struct interface *ifp) | |
479 | { | |
480 | struct route_node *rn; | |
481 | ||
482 | for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) | |
483 | { | |
484 | struct eigrp_interface *ei; | |
485 | ||
486 | if ((ei = rn->info) == NULL) | |
487 | continue; | |
488 | ||
489 | eigrp_if_down (ei); | |
490 | eigrp_if_up (ei); | |
491 | } | |
492 | } | |
493 | ||
494 | struct eigrp_interface * | |
495 | eigrp_if_lookup_by_local_addr (struct eigrp *eigrp, struct interface *ifp, | |
496 | struct in_addr address) | |
497 | { | |
498 | struct listnode *node; | |
499 | struct eigrp_interface *ei; | |
500 | ||
501 | for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) | |
502 | { | |
503 | if (ifp && ei->ifp != ifp) | |
504 | continue; | |
505 | ||
506 | if (IPV4_ADDR_SAME (&address, &ei->address->u.prefix4)) | |
507 | return ei; | |
508 | } | |
509 | ||
510 | return NULL; | |
511 | } | |
512 | ||
513 | /** | |
514 | * @fn eigrp_if_lookup_by_name | |
515 | * | |
516 | * @param[in] eigrp EIGRP process | |
517 | * @param[in] if_name Name of the interface | |
518 | * | |
519 | * @return struct eigrp_interface * | |
520 | * | |
521 | * @par | |
522 | * Function is used for lookup interface by name. | |
523 | */ | |
524 | struct eigrp_interface * | |
525 | eigrp_if_lookup_by_name (struct eigrp *eigrp, const char *if_name) | |
526 | { | |
527 | struct eigrp_interface *ei; | |
528 | struct listnode *node; | |
529 | ||
530 | /* iterate over all eigrp interfaces */ | |
531 | for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei)) | |
532 | { | |
533 | /* compare int name with eigrp interface's name */ | |
534 | if(strcmp(ei->ifp->name, if_name) == 0) | |
535 | { | |
536 | return ei; | |
537 | } | |
538 | } | |
539 | ||
540 | return NULL; | |
541 | } | |
542 | ||
543 | /* determine receiving interface by ifp and source address */ | |
544 | struct eigrp_interface * | |
545 | eigrp_if_lookup_recv_if (struct eigrp *eigrp, struct in_addr src, | |
546 | struct interface *ifp) | |
547 | { | |
548 | struct route_node *rn; | |
549 | struct prefix_ipv4 addr; | |
550 | struct eigrp_interface *ei, *match; | |
551 | ||
552 | addr.family = AF_INET; | |
553 | addr.prefix = src; | |
554 | addr.prefixlen = IPV4_MAX_BITLEN; | |
555 | ||
556 | match = NULL; | |
557 | ||
558 | for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) | |
559 | { | |
560 | ei = rn->info; | |
561 | ||
562 | if (!ei) /* oi can be NULL for PtP aliases */ | |
563 | continue; | |
564 | ||
565 | if (if_is_loopback (ei->ifp)) | |
566 | continue; | |
567 | ||
568 | if (prefix_match (CONNECTED_PREFIX (ei->connected), | |
569 | (struct prefix *) &addr)) | |
570 | { | |
571 | if ((match == NULL) | |
572 | || (match->address->prefixlen < ei->address->prefixlen)) | |
573 | match = ei; | |
574 | } | |
575 | } | |
576 | ||
577 | return match; | |
578 | } | |
579 | ||
580 | u_int32_t | |
581 | eigrp_bandwidth_to_scaled (u_int32_t bandwidth) | |
582 | { | |
583 | u_int64_t temp_bandwidth = (256ull * 10000000) / bandwidth; | |
584 | ||
585 | temp_bandwidth = | |
586 | temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth : EIGRP_MAX_METRIC; | |
587 | ||
588 | return (u_int32_t) temp_bandwidth; | |
589 | ||
590 | } | |
591 | ||
592 | u_int32_t | |
593 | eigrp_scaled_to_bandwidth (u_int32_t scaled) | |
594 | { | |
595 | u_int64_t temp_scaled = scaled * (256ull * 10000000); | |
596 | ||
597 | temp_scaled = | |
598 | temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC; | |
599 | ||
600 | return (u_int32_t) temp_scaled; | |
601 | } | |
602 | ||
603 | u_int32_t | |
604 | eigrp_delay_to_scaled (u_int32_t delay) | |
605 | { | |
606 | return delay * 256; | |
607 | } | |
608 | ||
609 | u_int32_t | |
610 | eigrp_scaled_to_delay (u_int32_t scaled) | |
611 | { | |
612 | return scaled / 256; | |
613 | } |