📄 ripd.c
字号:
{ /* If the route is not connected or localy generated one, use default-metric value*/ if (rinfo->type != ZEBRA_ROUTE_RIP && rinfo->type != ZEBRA_ROUTE_CONNECT && rinfo->metric != RIP_METRIC_INFINITY) rinfo->metric_out = rip->default_metric; } } /* Apply offset-list */ if (rinfo->metric != RIP_METRIC_INFINITY) rip_offset_list_apply_out (p, ifp, &rinfo->metric_out); if (rinfo->metric_out > RIP_METRIC_INFINITY) rinfo->metric_out = RIP_METRIC_INFINITY; /* Write RTE to the stream. */ num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp); if (num == rtemax) { if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) rip_auth_md5_set (s, ifp); ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp); if (ret >= 0 && IS_RIP_DEBUG_SEND) rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), stream_get_endp(s), "SEND"); num = 0; stream_reset (s); } } /* Flush unwritten RTE. */ if (num != 0) { if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5) rip_auth_md5_set (s, ifp); ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp); if (ret >= 0 && IS_RIP_DEBUG_SEND) rip_packet_dump ((struct rip_packet *)STREAM_DATA (s), stream_get_endp (s), "SEND"); num = 0; stream_reset (s); } /* Statistics updates. */ ri->sent_updates++;}/* Send RIP packet to the interface. */voidrip_update_interface (struct interface *ifp, u_char version, int route_type){ struct prefix_ipv4 *p; struct connected *connected; listnode node; struct sockaddr_in to; /* When RIP version is 2 and multicast enable interface. */ if (version == RIPv2 && if_is_multicast (ifp)) { if (IS_RIP_DEBUG_EVENT) zlog_info ("multicast announce on %s ", ifp->name); rip_output_process (ifp, NULL, route_type, version); return; } /* If we can't send multicast packet, send it with unicast. */ if (if_is_broadcast (ifp) || if_is_pointopoint (ifp)) { for (node = listhead (ifp->connected); node; nextnode (node)) { connected = getdata (node); /* Fetch broadcast address or poin-to-point destination address . */ p = (struct prefix_ipv4 *) connected->destination; if (p->family == AF_INET) { /* Destination address and port setting. */ memset (&to, 0, sizeof (struct sockaddr_in)); to.sin_addr = p->prefix; to.sin_port = htons (RIP_PORT_DEFAULT); if (IS_RIP_DEBUG_EVENT) zlog_info ("%s announce to %s on %s", if_is_pointopoint (ifp) ? "unicast" : "broadcast", inet_ntoa (to.sin_addr), ifp->name); rip_output_process (ifp, &to, route_type, version); } } }}/* Update send to all interface and neighbor. */voidrip_update_process (int route_type){ listnode node; struct interface *ifp; struct rip_interface *ri; struct route_node *rp; struct sockaddr_in to; struct prefix_ipv4 *p; /* Send RIP update to each interface. */ for (node = listhead (iflist); node; nextnode (node)) { ifp = getdata (node); if (if_is_loopback (ifp)) continue; if (! if_is_up (ifp)) continue; /* Fetch RIP interface information. */ ri = ifp->info; /* When passive interface is specified, suppress announce to the interface. */ if (ri->passive) continue; if (ri->running) { if (IS_RIP_DEBUG_EVENT) { if (ifp->name) zlog_info ("SEND UPDATE to %s ifindex %d", ifp->name, ifp->ifindex); else zlog_info ("SEND UPDATE to _unknown_ ifindex %d", ifp->ifindex); } /* If there is no version configuration in the interface, use rip's version setting. */ if (ri->ri_send == RI_RIP_UNSPEC) { if (rip->version == RIPv1) rip_update_interface (ifp, RIPv1, route_type); else rip_update_interface (ifp, RIPv2, route_type); } /* If interface has RIP version configuration use it. */ else { if (ri->ri_send & RIPv1) rip_update_interface (ifp, RIPv1, route_type); if (ri->ri_send & RIPv2) rip_update_interface (ifp, RIPv2, route_type); } } } /* RIP send updates to each neighbor. */ for (rp = route_top (rip->neighbor); rp; rp = route_next (rp)) if (rp->info != NULL) { p = (struct prefix_ipv4 *) &rp->p; ifp = if_lookup_address (p->prefix); if (! ifp) { zlog_warn ("Neighbor %s doesn't exist direct connected network", inet_ntoa (p->prefix)); continue; } /* Set destination address and port */ memset (&to, 0, sizeof (struct sockaddr_in)); to.sin_addr = p->prefix; to.sin_port = htons (RIP_PORT_DEFAULT); /* RIP version is rip's configuration. */ rip_output_process (ifp, &to, route_type, rip->version); }}/* RIP's periodical timer. */intrip_update (struct thread *t){ /* Clear timer pointer. */ rip->t_update = NULL; if (IS_RIP_DEBUG_EVENT) zlog_info ("update timer fire!"); /* Process update output. */ rip_update_process (rip_all_route); /* Triggered updates may be suppressed if a regular update is due by the time the triggered update would be sent. */ if (rip->t_triggered_interval) { thread_cancel (rip->t_triggered_interval); rip->t_triggered_interval = NULL; } rip->trigger = 0; /* Register myself. */ rip_event (RIP_UPDATE_EVENT, 0); return 0;}/* Walk down the RIP routing table then clear changed flag. */voidrip_clear_changed_flag (){ struct route_node *rp; struct rip_info *rinfo; for (rp = route_top (rip->table); rp; rp = route_next (rp)) if ((rinfo = rp->info) != NULL) if (rinfo->flags & RIP_RTF_CHANGED) rinfo->flags &= ~RIP_RTF_CHANGED;}/* Triggered update interval timer. */intrip_triggered_interval (struct thread *t){ int rip_triggered_update (struct thread *); rip->t_triggered_interval = NULL; if (rip->trigger) { rip->trigger = 0; rip_triggered_update (t); } return 0;} /* Execute triggered update. */intrip_triggered_update (struct thread *t){ int interval; /* Clear thred pointer. */ rip->t_triggered_update = NULL; /* Cancel interval timer. */ if (rip->t_triggered_interval) { thread_cancel (rip->t_triggered_interval); rip->t_triggered_interval = NULL; } rip->trigger = 0; /* Logging triggered update. */ if (IS_RIP_DEBUG_EVENT) zlog_info ("triggered update!"); /* Split Horizon processing is done when generating triggered updates as well as normal updates (see section 2.6). */ rip_update_process (rip_changed_route); /* Once all of the triggered updates have been generated, the route change flags should be cleared. */ rip_clear_changed_flag (); /* After a triggered update is sent, a timer should be set for a random interval between 1 and 5 seconds. If other changes that would trigger updates occur before the timer expires, a single update is triggered when the timer expires. */ interval = (random () % 5) + 1; rip->t_triggered_interval = thread_add_timer (master, rip_triggered_interval, NULL, interval); return 0;}/* Withdraw redistributed route. */voidrip_redistribute_withdraw (int type){ struct route_node *rp; struct rip_info *rinfo; if (!rip) return; for (rp = route_top (rip->table); rp; rp = route_next (rp)) if ((rinfo = rp->info) != NULL) { if (rinfo->type == type && rinfo->sub_type != RIP_ROUTE_INTERFACE) { /* Perform poisoned reverse. */ rinfo->metric = RIP_METRIC_INFINITY; RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect, rip->garbage_time); RIP_TIMER_OFF (rinfo->t_timeout); rinfo->flags |= RIP_RTF_CHANGED; rip_event (RIP_TRIGGERED_UPDATE, 0); } }}/* Create new RIP instance and set it to global variable. */intrip_create (){ rip = XMALLOC (MTYPE_RIP, sizeof (struct rip)); memset (rip, 0, sizeof (struct rip)); /* Set initial value. */ rip->version = RIPv2; rip->update_time = RIP_UPDATE_TIMER_DEFAULT; rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT; rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT; rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT; /* Initialize RIP routig table. */ rip->table = route_table_init (); rip->route = route_table_init (); rip->neighbor = route_table_init (); /* Make output stream. */ rip->obuf = stream_new (1500); /* Make socket. */ rip->sock = rip_create_socket (); if (rip->sock < 0) return rip->sock; /* Create read and timer thread. */ rip_event (RIP_READ, rip->sock); rip_event (RIP_UPDATE_EVENT, 1); return 0;}/* Sned RIP request to the destination. */intrip_request_send (struct sockaddr_in *to, struct interface *ifp, u_char version){ struct rte *rte; struct rip_packet rip_packet; memset (&rip_packet, 0, sizeof (rip_packet)); rip_packet.command = RIP_REQUEST; rip_packet.version = version; rte = rip_packet.rte; rte->metric = htonl (RIP_METRIC_INFINITY); return rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), to, ifp);}intrip_update_jitter (unsigned long time){ return ((rand () % (time + 1)) - (time / 2));}voidrip_event (enum rip_event event, int sock){ int jitter = 0; switch (event) { case RIP_READ: rip->t_read = thread_add_read (master, rip_read, NULL, sock); break; case RIP_UPDATE_EVENT: if (rip->t_update) { thread_cancel (rip->t_update); rip->t_update = NULL; } jitter = rip_update_jitter (rip->update_time); rip->t_update = thread_add_timer (master, rip_update, NULL, sock ? 2 : rip->update_time + jitter); break; case RIP_TRIGGERED_UPDATE: if (rip->t_triggered_interval) rip->trigger = 1; else if (! rip->t_triggered_update) rip->t_triggered_update = thread_add_event (master, rip_triggered_update, NULL, 0); break; default: break; }}DEFUN (router_rip, router_rip_cmd, "router rip", "Enable a routing process\n" "Routing Information Protocol (RIP)\n"){ int ret; /* If rip is not enabled before. */ if (! rip) { ret = rip_create (); if (ret < 0) { zlog_info ("Can't create RIP"); return CMD_WARNING; } } vty->node = RIP_NODE; vty->index = rip; return CMD_SUCCESS;}DEFUN (no_router_rip, no_router_rip_cmd, "no router rip", NO_STR "Enable a routing process\n" "Routing Information Protocol (RIP)\n"){ if (rip) rip_clean (); return CMD_SUCCESS;}DEFUN (rip_version, rip_version_cmd, "version <1-2>", "Set routing protocol version\n" "version\n"){ int version; version = atoi (argv[0]); if (version != RIPv1 && version != RIPv2) { vty_out (vty, "invalid rip version %d%s", version, VTY_NEWLINE); return CMD_WARNING; } rip->version = version; return CMD_SUCCESS;} DEFUN (no_rip_version, no_rip_version_cmd, "no version", NO_STR "Set routing protocol version\n"){ /* Set RIP version to the default. */ rip->version = RIPv2; return CMD_SUCCESS;} ALIAS (no_rip_version, no_rip_version_val_cmd, "no version <1-2>", NO_STR "Set routing protocol version\n" "version\n");DEFUN (rip_route, rip_route_cmd, "route A.B.C.D/M", "RIP static route configuration\n" "IP prefix <network>/<length>\n"){ int ret; struct prefix_ipv4 p; struct route_node *node; ret = str2prefix_ipv4 (argv[0], &p); if (ret < 0) { vty_out (vty, "Malformed address%s", VTY_NEWLINE); return CMD_WARNING; } apply_mask_ipv4 (&p); /* For router rip configuration. */ node = route_node_get (rip->route, (struct prefix *) &p); if (node->info) { vty_out (vty, "There is already same static route.%s", VTY_NEWLINE); route_unlock_node (node); return CMD_WARNING; } node->info = "static"; rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -