diff options
author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2009-08-24 11:48:34 +0000 |
---|---|---|
committer | David Lamparter <equinox@diac24.net> | 2010-02-04 01:18:21 +0100 |
commit | 58bfa5562817306f14cd7d41953a2740056e1afc (patch) | |
tree | a8cf512088255220ce493279229aed05670cde51 | |
parent | f03edb371c3e0b389f15600ceb283055033085e6 (diff) | |
download | quagga-58bfa5562817306f14cd7d41953a2740056e1afc.tar.bz2 quagga-58bfa5562817306f14cd7d41953a2740056e1afc.tar.xz |
ospfd: Add new host route command
Add static host routes into router LSA.
See RFC 2328 chapter 12.4 and Appendix C.7
Syntax:
router ospf
ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all) cost <0-65535>
no ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all)
* ospfd/ospf_route.h: Add struct ospf_host_route
* ospfd/ospf_lsa.c: (router_lsa_link_set) Add host routes to Router LSA.
* ospfd/ospf_vtc.c: Impl. ip_ospf_host_cmd and no_ip_ospf_host_cmd.
(ospf_config_write) Write out host routes to config.
* ospfd/ospf_ospfd.c: (ospf_new) Allocate new host route list.
(ospf_finish_filnal) Free host list.
(ospf_area_check_free) Check if any host routes in
area before freeing.
* ospfd/ospf_ospfd.h: Add a host list to struct ospf.
-rw-r--r-- | ospfd/ospf_lsa.c | 7 | ||||
-rw-r--r-- | ospfd/ospf_route.h | 6 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 137 | ||||
-rw-r--r-- | ospfd/ospfd.c | 14 | ||||
-rw-r--r-- | ospfd/ospfd.h | 3 |
5 files changed, 164 insertions, 3 deletions
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index e708d5e2..8737bca2 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -657,6 +657,8 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi) static int router_lsa_link_set (struct stream *s, struct ospf_area *area) { + struct ospf_host_route *host; + struct in_addr host_mask = {~0}; /* All ones */ struct listnode *node; struct ospf_interface *oi; int links = 0; @@ -694,7 +696,10 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area) } } } - + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (host->area == NULL || host->area == area) + links += link_info_set (s, host->host_addr, host_mask, + LSA_LINK_TYPE_STUB, 0, host->cost); return links; } diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h index 17ab68e5..5483aaf5 100644 --- a/ospfd/ospf_route.h +++ b/ospfd/ospf_route.h @@ -121,6 +121,12 @@ struct ospf_route } u; }; +struct ospf_host_route { + struct in_addr host_addr; + u_int32_t cost; /* i.e. metric. */ + struct ospf_area *area; /* NULL == all areas */ +}; + extern struct ospf_path *ospf_path_new (void); extern void ospf_path_free (struct ospf_path *); extern struct ospf_path *ospf_path_lookup (struct list *, struct ospf_path *); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index adc822a7..07e1f32d 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7389,6 +7389,123 @@ DEFUN (show_ip_ospf_route, return CMD_SUCCESS; } +DEFUN (ip_ospf_host, + ip_ospf_host_cmd, + "ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all) cost <0-65535>", + "OSPF specific commands\n" + "Add a host route to OPSF\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + u_int32_t cost; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + cost = strtol (argv[2], NULL, 10); + /* cost range is <0-65535>. */ + if (cost < 0 || cost > 65535) + { + vty_out (vty, "cost is invalid%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); /* returns if error */ + area = ospf_area_get (ospf, area_id, format); + } + + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (!node) + { + host = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf_host_route)); + listnode_add (ospf->hostlist, host); + } + host->host_addr = host_addr; + host->cost = cost; + host->area = area; + + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_host, + no_ip_ospf_host_cmd, + "no ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all)", + NO_STR + "OSPF specific commands\n" + "Host route in IP address format\n") +{ + struct ospf *ospf; + struct ospf_area *area = NULL; + struct in_addr host_addr, area_id; + struct ospf_host_route *host = NULL; + struct listnode *node; + int ret, format; + + ospf = ospf_lookup (); + if (ospf == NULL) + { + vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE); + return CMD_SUCCESS; + } + ret = inet_aton (argv[0], &host_addr); + if (!ret) + { + vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE); + return CMD_WARNING; + } + + if (strcmp(argv[1], "all") != 0) + { + VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); + area = ospf_area_get (ospf, area_id, format); + } + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) && + area == host->area) + break; + + if (node) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + if (!area) + for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area)) + ospf_router_lsa_timer_add(area); + else + ospf_router_lsa_timer_add(area); + } + return CMD_SUCCESS; +} + const char *ospf_abr_type_str[] = { @@ -7970,6 +8087,7 @@ ospf_config_write (struct vty *vty) struct interface *ifp; struct ospf_interface *oi; struct listnode *node; + struct ospf_host_route *host; int write = 0; ospf = ospf_lookup (); @@ -8037,7 +8155,20 @@ ospf_config_write (struct vty *vty) /* passive-interface print. */ if (ospf->passive_interface_default == OSPF_IF_PASSIVE) vty_out (vty, " passive-interface default%s", VTY_NEWLINE); - + + for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host)) + { + char buf[28]; + + if (host->area) + area_id2str(buf, sizeof(buf), host->area); + else + strcpy(buf, "all"); + vty_out (vty, " ip ospf host %s area %s cost %d%s", + inet_ntoa (host->host_addr), + buf, host->cost, VTY_NEWLINE); + } + for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp)) if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface) && IF_DEF_PARAMS (ifp)->passive_interface != @@ -8523,6 +8654,10 @@ ospf_vty_init (void) install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd); install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd); + /* "ip ospf host" commands. */ + install_element (OSPF_NODE, &ip_ospf_host_cmd); + install_element (OSPF_NODE, &no_ip_ospf_host_cmd); + /* Init interface related vty commands. */ ospf_vty_if_init (); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index a7553e73..b11ee1bb 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -231,7 +231,7 @@ ospf_new (void) } new->t_read = thread_add_read (master, ospf_read, new, new->fd); new->oi_write_q = list_new (); - + new->hostlist = list_new(); /* host route list */ return new; } @@ -401,6 +401,7 @@ ospf_finish_final (struct ospf *ospf) struct ospf_lsa *lsa; struct ospf_interface *oi; struct ospf_area *area; + struct ospf_host_route *host; struct ospf_vl_data *vl_data; struct listnode *node, *nnode; int i; @@ -471,6 +472,12 @@ ospf_finish_final (struct ospf *ospf) ospf_area_free (area); } + for (ALL_LIST_ELEMENTS (ospf->hostlist, node, nnode, host)) + { + listnode_delete (ospf->hostlist, host); + XFREE (MTYPE_OSPF_TOP, host); + } + /* Cancel all timers. */ OSPF_TIMER_OFF (ospf->t_external_lsa); OSPF_TIMER_OFF (ospf->t_router_lsa_update); @@ -646,6 +653,8 @@ ospf_area_free (struct ospf_area *area) void ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) { + struct ospf_host_route *host; + struct listnode *node; struct ospf_area *area; area = ospf_area_lookup_by_area_id (ospf, area_id); @@ -660,6 +669,9 @@ ospf_area_check_free (struct ospf *ospf, struct in_addr area_id) IMPORT_NAME (area) == NULL && area->auth_type == OSPF_AUTH_NULL) { + for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host)) + if (!host->area || host->area == area) + return; listnode_delete (ospf->areas, area); ospf_area_free (area); } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index b24b3ced..6ced9c72 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -327,6 +327,9 @@ struct ospf u_int32_t rx_lsa_count; struct route_table *distance_table; + + /* Host route list */ + struct list *hostlist; }; /* OSPF area structure. */ |