diff options
Diffstat (limited to 'ospfd')
-rw-r--r-- | ospfd/ospf_abr.h | 1 | ||||
-rw-r--r-- | ospfd/ospf_asbr.c | 5 | ||||
-rw-r--r-- | ospfd/ospf_asbr.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_dump.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_interface.c | 18 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 45 | ||||
-rw-r--r-- | ospfd/ospf_main.c | 1 | ||||
-rw-r--r-- | ospfd/ospf_network.c | 36 | ||||
-rw-r--r-- | ospfd/ospf_nsm.c | 3 | ||||
-rw-r--r-- | ospfd/ospf_packet.c | 267 | ||||
-rw-r--r-- | ospfd/ospf_route.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_routemap.c | 223 | ||||
-rw-r--r-- | ospfd/ospf_spf.c | 7 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 199 | ||||
-rw-r--r-- | ospfd/ospf_vty.h | 1 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 28 | ||||
-rw-r--r-- | ospfd/ospfd.c | 2 | ||||
-rw-r--r-- | ospfd/ospfd.h | 9 |
18 files changed, 658 insertions, 194 deletions
diff --git a/ospfd/ospf_abr.h b/ospfd/ospf_abr.h index e367e447..2a728936 100644 --- a/ospfd/ospf_abr.h +++ b/ospfd/ospf_abr.h @@ -52,7 +52,6 @@ struct ospf_area_range /* Configured range cost. */ u_int32_t cost_config; -#define OSPF_AREA_RANGE_COST_UNSPEC -1U }; /* Prototypes. */ diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 122e70b4..4b536903 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -135,7 +135,8 @@ ospf_route_map_set_compare (struct route_map_set_values *values1, /* Add an External info for AS-external-LSA. */ struct external_info * ospf_external_info_add (u_char type, struct prefix_ipv4 p, - ifindex_t ifindex, struct in_addr nexthop) + ifindex_t ifindex, struct in_addr nexthop, + u_short tag) { struct external_info *new; struct route_node *rn; @@ -162,7 +163,7 @@ ospf_external_info_add (u_char type, struct prefix_ipv4 p, new->p = p; new->ifindex = ifindex; new->nexthop = nexthop; - new->tag = 0; + new->tag = tag; if (rn) rn->info = new; diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index d151cb14..2709a6c0 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -62,7 +62,8 @@ extern int ospf_route_map_set_compare (struct route_map_set_values *, extern struct external_info *ospf_external_info_add (u_char, struct prefix_ipv4, ifindex_t, - struct in_addr); + struct in_addr, + u_short); extern void ospf_external_info_delete (u_char, struct prefix_ipv4); extern struct external_info *ospf_external_info_lookup (u_char, struct prefix_ipv4 *); diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c index fb43210a..68792e21 100644 --- a/ospfd/ospf_dump.c +++ b/ospfd/ospf_dump.c @@ -204,7 +204,7 @@ ospf_if_name_string (struct ospf_interface *oi) static char buf[OSPF_IF_STRING_MAXLEN] = ""; u_int32_t ifaddr; - if (!oi) + if (!oi || !oi->address) return "inactive"; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index f4242b0b..fd3e239f 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -347,7 +347,12 @@ ospf_if_is_configured (struct ospf *ospf, struct in_addr *address) for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) if (oi->type != OSPF_IFTYPE_VIRTUALLINK) { - if (oi->type == OSPF_IFTYPE_POINTOPOINT) + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) + { + if (htonl(oi->ifp->ifindex) == address->s_addr) + return oi; + } + else if (oi->type == OSPF_IFTYPE_POINTOPOINT) { /* special leniency: match if addr is anywhere on peer subnet */ if (prefix_match(CONNECTED_PREFIX(oi->connected), @@ -471,8 +476,10 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src, if (if_is_loopback (oi->ifp)) continue; - if (prefix_match (CONNECTED_PREFIX(oi->connected), - (struct prefix *) &addr)) + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) + match = oi; + else if (prefix_match (CONNECTED_PREFIX(oi->connected), + (struct prefix *) &addr)) { if ( (match == NULL) || (match->address->prefixlen < oi->address->prefixlen) @@ -866,6 +873,11 @@ ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data) snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count); vi = if_create (ifname, strnlen(ifname, sizeof(ifname))); + /* + * if_create sets ZEBRA_INTERFACE_LINKDETECTION + * virtual links don't need this. + */ + UNSET_FLAG (vi->status, ZEBRA_INTERFACE_LINKDETECTION); co = connected_new (); co->ifp = vi; listnode_add (vi->connected, co); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 634bc435..e9d1a858 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -543,7 +543,7 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) { int links = 0; struct ospf_neighbor *nbr; - struct in_addr id, mask; + struct in_addr id, mask, data; u_int16_t cost = ospf_link_cost (oi); if (IS_DEBUG_OSPF (lsa, LSA_GENERATE)) @@ -552,19 +552,34 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) if ((nbr = ospf_nbr_lookup_ptop (oi))) if (nbr->state == NSM_Full) { - /* For unnumbered point-to-point networks, the Link Data field - should specify the interface's MIB-II ifIndex value. */ - links += link_info_set (s, nbr->router_id, oi->address->u.prefix4, - LSA_LINK_TYPE_POINTOPOINT, 0, cost); + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) + { + /* For unnumbered point-to-point networks, the Link Data field + should specify the interface's MIB-II ifIndex value. */ + data.s_addr = htonl(oi->ifp->ifindex); + links += link_info_set (s, nbr->router_id, data, + LSA_LINK_TYPE_POINTOPOINT, 0, cost); + } + else + { + links += link_info_set (s, nbr->router_id, + oi->address->u.prefix4, + LSA_LINK_TYPE_POINTOPOINT, 0, cost); + } } - /* Regardless of the state of the neighboring router, we must - add a Type 3 link (stub network). - N.B. Options 1 & 2 share basically the same logic. */ - masklen2ip (oi->address->prefixlen, &mask); - id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr; - links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, - oi->output_cost); + /* no need for a stub link for unnumbered interfaces */ + if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) + { + /* Regardless of the state of the neighboring router, we must + add a Type 3 link (stub network). + N.B. Options 1 & 2 share basically the same logic. */ + masklen2ip (oi->address->prefixlen, &mask); + id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr; + links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0, + oi->output_cost); + } + return links; } @@ -1649,8 +1664,8 @@ ospf_external_lsa_body_set (struct stream *s, struct external_info *ei, /* Put forwarding address. */ stream_put_ipv4 (s, fwd_addr.s_addr); - /* Put route tag -- This value should be introduced from configuration. */ - stream_putl (s, 0); + /* Put route tag -- only first 16bits are used for compatibility */ + stream_putl (s, ei->tag); } /* Create new external-LSA. */ @@ -2163,7 +2178,7 @@ ospf_default_originate_timer (struct thread *thread) /* If there is no default route via redistribute, then originate AS-external-LSA with nexthop 0 (self). */ nexthop.s_addr = 0; - ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop); + ospf_external_info_add (DEFAULT_ROUTE, p, 0, nexthop, 0); } if ((ei = ospf_default_external_info (ospf))) diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index f373650c..32b64e2a 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -303,6 +303,7 @@ main (int argc, char **argv) /* OSPF vty inits. */ ospf_vty_init (); ospf_vty_show_init (); + ospf_vty_clear_init (); ospf_route_map_init (); #ifdef HAVE_SNMP diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index 02ddf92f..62ea6da4 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -163,6 +163,9 @@ ospf_sock_init (void) { int ospf_sock; int ret, hincl = 1; + int bufsize = (8 * 1024 * 1024); + int optval; + socklen_t optlen = sizeof(optval); if ( ospfd_privs.change (ZPRIVS_RAISE) ) zlog_err ("ospf_sock_init: could not raise privs, %s", @@ -221,6 +224,39 @@ ospf_sock_init (void) zlog_err ("ospf_sock_init: could not lower privs, %s", safe_strerror (errno) ); } + + if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF, + &bufsize, sizeof (bufsize))) < 0) + { + zlog_err ("Couldn't increase raw rbuf size: %s\n", safe_strerror(errno)); + } + + if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF, + &optval, &optlen)) < 0) + { + zlog_err("getsockopt of SO_RCVBUF failed with error %s\n", safe_strerror(errno)); + } + if (optval < bufsize) + { + zlog_err("Unable to SO_RCVBUF to %d, set to %d\n", bufsize, optval); + } + + + if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF, + &bufsize, sizeof (bufsize))) < 0) + { + zlog_err ("Couldn't increase raw wbuf size: %s\n", safe_strerror(errno)); + } + + if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF, + &optval, &optlen)) < 0) + { + zlog_err ("getsockopt of SO_SNDBUF failed with error %s\n", safe_strerror(errno)); + } + if (optval < bufsize) + { + zlog_err ("Unable to SO_SNDBUF to %d, set to %d\n", bufsize, optval); + } return ospf_sock; } diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index b43d8855..64cc246b 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -316,7 +316,8 @@ nsm_exchange_done (struct ospf_neighbor *nbr) return NSM_Full; /* Send Link State Request. */ - ospf_ls_req_send (nbr); + if (nbr->t_ls_req == NULL) + ospf_ls_req_send (nbr); return NSM_Loading; } diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 25f70bba..48fe0829 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -633,6 +633,7 @@ ospf_write (struct thread *thread) { struct ospf *ospf = THREAD_ARG (thread); struct ospf_interface *oi; + struct ospf_interface *last_serviced_oi = NULL; struct ospf_packet *op; struct sockaddr_in sa_dst; struct ip iph; @@ -647,6 +648,7 @@ ospf_write (struct thread *thread) u_int16_t maxdatasize; #endif /* WANT_OSPF_WRITE_FRAGMENT */ #define OSPF_WRITE_IPHL_SHIFT 2 + int pkt_count = 0; ospf->t_write = NULL; @@ -659,143 +661,173 @@ ospf_write (struct thread *thread) /* seed ipid static with low order bits of time */ if (ipid == 0) ipid = (time(NULL) & 0xffff); - - /* convenience - max OSPF data per packet, - * and reliability - not more data, than our - * socket can accept - */ - maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) - - sizeof (struct ip); #endif /* WANT_OSPF_WRITE_FRAGMENT */ - - /* Get one packet from queue. */ - op = ospf_fifo_head (oi->obuf); - assert (op); - assert (op->length >= OSPF_HEADER_SIZE); - - if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS) - || op->dst.s_addr == htonl (OSPF_ALLDROUTERS)) - ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex); - - /* Rewrite the md5 signature & update the seq */ - ospf_make_md5_digest (oi, op); - /* Retrieve OSPF packet type. */ - stream_set_getp (op->s, 1); - type = stream_getc (op->s); + while ((pkt_count < ospf->write_oi_count) && oi && (last_serviced_oi != oi)) + { + /* If there is only packet in the queue, the oi is removed from + write-q, so fix up the last interface that was serviced */ + if (last_serviced_oi == NULL) { + last_serviced_oi = oi; + } + pkt_count++; + /* convenience - max OSPF data per packet, + * and reliability - not more data, than our + * socket can accept + */ +#if defined (WANT_OSPF_WRITE_FRAGMENT) + maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) - + sizeof (struct ip); +#endif + + /* Get one packet from queue. */ + op = ospf_fifo_head (oi->obuf); + assert (op); + assert (op->length >= OSPF_HEADER_SIZE); + + if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS) + || op->dst.s_addr == htonl (OSPF_ALLDROUTERS)) + ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex); + + /* Rewrite the md5 signature & update the seq */ + ospf_make_md5_digest (oi, op); + + /* Retrieve OSPF packet type. */ + stream_set_getp (op->s, 1); + type = stream_getc (op->s); - /* reset get pointer */ - stream_set_getp (op->s, 0); + /* reset get pointer */ + stream_set_getp (op->s, 0); - memset (&iph, 0, sizeof (struct ip)); - memset (&sa_dst, 0, sizeof (sa_dst)); + memset (&iph, 0, sizeof (struct ip)); + memset (&sa_dst, 0, sizeof (sa_dst)); - sa_dst.sin_family = AF_INET; + sa_dst.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sa_dst.sin_len = sizeof(sa_dst); + sa_dst.sin_len = sizeof(sa_dst); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sa_dst.sin_addr = op->dst; - sa_dst.sin_port = htons (0); - - /* Set DONTROUTE flag if dst is unicast. */ - if (oi->type != OSPF_IFTYPE_VIRTUALLINK) - if (!IN_MULTICAST (htonl (op->dst.s_addr))) - flags = MSG_DONTROUTE; - - iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT; - /* it'd be very strange for header to not be 4byte-word aligned but.. */ - if ( sizeof (struct ip) - > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) ) - iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */ + sa_dst.sin_addr = op->dst; + sa_dst.sin_port = htons (0); + + /* Set DONTROUTE flag if dst is unicast. */ + if (oi->type != OSPF_IFTYPE_VIRTUALLINK) + if (!IN_MULTICAST (htonl (op->dst.s_addr))) + flags = MSG_DONTROUTE; + + iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT; + /* it'd be very strange for header to not be 4byte-word aligned but.. */ + if ( sizeof (struct ip) + > (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) ) + iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */ - iph.ip_v = IPVERSION; - iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; - iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length; + iph.ip_v = IPVERSION; + iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; + iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length; #if defined(__DragonFly__) - /* - * DragonFly's raw socket expects ip_len/ip_off in network byte order. - */ - iph.ip_len = htons(iph.ip_len); + /* + * DragonFly's raw socket expects ip_len/ip_off in network byte order. + */ + iph.ip_len = htons(iph.ip_len); #endif #ifdef WANT_OSPF_WRITE_FRAGMENT - /* XXX-MT: not thread-safe at all.. - * XXX: this presumes this is only programme sending OSPF packets - * otherwise, no guarantee ipid will be unique - */ - iph.ip_id = ++ipid; + /* XXX-MT: not thread-safe at all.. + * XXX: this presumes this is only programme sending OSPF packets + * otherwise, no guarantee ipid will be unique + */ + iph.ip_id = ++ipid; #endif /* WANT_OSPF_WRITE_FRAGMENT */ - iph.ip_off = 0; - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - iph.ip_ttl = OSPF_VL_IP_TTL; - else - iph.ip_ttl = OSPF_IP_TTL; - iph.ip_p = IPPROTO_OSPFIGP; - iph.ip_sum = 0; - iph.ip_src.s_addr = oi->address->u.prefix4.s_addr; - iph.ip_dst.s_addr = op->dst.s_addr; - - memset (&msg, 0, sizeof (msg)); - msg.msg_name = (caddr_t) &sa_dst; - msg.msg_namelen = sizeof (sa_dst); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - iov[0].iov_base = (char*)&iph; - iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT; - iov[1].iov_base = STREAM_PNT (op->s); - iov[1].iov_len = op->length; + iph.ip_off = 0; + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + iph.ip_ttl = OSPF_VL_IP_TTL; + else + iph.ip_ttl = OSPF_IP_TTL; + iph.ip_p = IPPROTO_OSPFIGP; + iph.ip_sum = 0; + iph.ip_src.s_addr = oi->address->u.prefix4.s_addr; + iph.ip_dst.s_addr = op->dst.s_addr; + + memset (&msg, 0, sizeof (msg)); + msg.msg_name = (caddr_t) &sa_dst; + msg.msg_namelen = sizeof (sa_dst); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + iov[0].iov_base = (char*)&iph; + iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT; + iov[1].iov_base = STREAM_PNT (op->s); + iov[1].iov_len = op->length; - /* Sadly we can not rely on kernels to fragment packets because of either - * IP_HDRINCL and/or multicast destination being set. - */ + /* Sadly we can not rely on kernels to fragment packets because of either + * IP_HDRINCL and/or multicast destination being set. + */ #ifdef WANT_OSPF_WRITE_FRAGMENT - if ( op->length > maxdatasize ) - ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize, - oi->ifp->mtu, flags, type); + if ( op->length > maxdatasize ) + ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize, + oi->ifp->mtu, flags, type); #endif /* WANT_OSPF_WRITE_FRAGMENT */ - /* send final fragment (could be first) */ - sockopt_iphdrincl_swab_htosys (&iph); - ret = sendmsg (ospf->fd, &msg, flags); - sockopt_iphdrincl_swab_systoh (&iph); + /* send final fragment (could be first) */ + sockopt_iphdrincl_swab_htosys (&iph); + ret = sendmsg (ospf->fd, &msg, flags); + sockopt_iphdrincl_swab_systoh (&iph); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug ("ospf_write to %s, " + "id %d, off %d, len %d, interface %s, mtu %u:", + inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, + oi->ifp->name, oi->ifp->mtu); - if (ret < 0) - zlog_warn ("*** sendmsg in ospf_write failed to %s, " - "id %d, off %d, len %d, interface %s, mtu %u: %s", - inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, - oi->ifp->name, oi->ifp->mtu, safe_strerror (errno)); + if (ret < 0) + zlog_warn ("*** sendmsg in ospf_write failed to %s, " + "id %d, off %d, len %d, interface %s, mtu %u: %s", + inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len, + oi->ifp->name, oi->ifp->mtu, safe_strerror (errno)); - /* Show debug sending packet. */ - if (IS_DEBUG_OSPF_PACKET (type - 1, SEND)) - { - if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) - { - zlog_debug ("-----------------------------------------------------"); - ospf_ip_header_dump (&iph); - stream_set_getp (op->s, 0); - ospf_packet_dump (op->s); - } + /* Show debug sending packet. */ + if (IS_DEBUG_OSPF_PACKET (type - 1, SEND)) + { + if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) + { + zlog_debug ("-----------------------------------------------------"); + ospf_ip_header_dump (&iph); + stream_set_getp (op->s, 0); + ospf_packet_dump (op->s); + } - zlog_debug ("%s sent to [%s] via [%s].", - LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst), - IF_NAME (oi)); + zlog_debug ("%s sent to [%s] via [%s].", + LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst), + IF_NAME (oi)); - if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) - zlog_debug ("-----------------------------------------------------"); - } + if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) + zlog_debug ("-----------------------------------------------------"); + } - /* Now delete packet from queue. */ - ospf_packet_delete (oi); + /* Now delete packet from queue. */ + ospf_packet_delete (oi); - /* Move this interface to the tail of write_q to + /* Move this interface to the tail of write_q to serve everyone in a round robin fashion */ - listnode_move_to_tail (ospf->oi_write_q, node); - if (ospf_fifo_head (oi->obuf) == NULL) - { - oi->on_write_q = 0; list_delete_node (ospf->oi_write_q, node); + if (ospf_fifo_head (oi->obuf) == NULL) + { + oi->on_write_q = 0; + last_serviced_oi = NULL; + oi = NULL; + } + else + { + listnode_add (ospf->oi_write_q, oi); + } + + /* Setup to service from the head of the queue again */ + if (!list_isempty (ospf->oi_write_q)) + { + node = listhead (ospf->oi_write_q); + assert (node); + oi = listgetdata (node); + assert (oi); + } } /* If packets still remain in queue, call write thread. */ @@ -1162,6 +1194,9 @@ ospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, /* Save received neighbor values from DD. */ ospf_db_desc_save_current (nbr, dd); + + if (!nbr->t_ls_req) + ospf_ls_req_send (nbr); } static int @@ -3022,7 +3057,8 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s) int flag = 0; /* Set netmask of interface. */ - if (oi->type != OSPF_IFTYPE_POINTOPOINT && + if (!(CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED) && + oi->type == OSPF_IFTYPE_POINTOPOINT) && oi->type != OSPF_IFTYPE_VIRTUALLINK) masklen2ip (oi->address->prefixlen, &mask); else @@ -3830,9 +3866,12 @@ ospf_ls_ack_send_list (struct ospf_interface *oi, struct list *ack, /* Set packet length. */ op->length = length; - /* Set destination IP address. */ - op->dst = dst; - + /* Decide destination address. */ + if (oi->type == OSPF_IFTYPE_POINTOPOINT) + op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS); + else + op->dst.s_addr = dst.s_addr; + /* Add packet to the interface output queue. */ ospf_packet_add (oi, op); diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index eb7829ac..51e6ebae 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -783,7 +783,7 @@ ospf_route_copy_nexthops_from_vertex (struct ospf_route *to, path = ospf_path_new (); path->nexthop = nexthop->router; path->ifindex = nexthop->oi->ifp->ifindex; - listnode_add (to->paths, path); + listnode_add (to->paths, path); } } } diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index d0ebce66..133b1e36 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -108,10 +108,10 @@ ospf_route_match_delete (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } @@ -131,10 +131,10 @@ ospf_route_match_add (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } @@ -154,10 +154,10 @@ ospf_route_set_add (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } @@ -178,10 +178,10 @@ ospf_route_set_delete (struct vty *vty, struct route_map_index *index, switch (ret) { case RMAP_RULE_MISSING: - vty_out (vty, "%% Can't find rule.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Can't find rule.%s", VTY_NEWLINE); return CMD_WARNING; case RMAP_COMPILE_ERROR: - vty_out (vty, "%% Argument is malformed.%s", VTY_NEWLINE); + vty_out (vty, "%% OSPF Argument is malformed.%s", VTY_NEWLINE); return CMD_WARNING; } } @@ -417,6 +417,67 @@ struct route_map_rule_cmd route_match_interface_cmd = route_match_interface_free }; +/* Match function return 1 if match is success else return zero. */ +static route_map_result_t +route_match_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct external_info *ei; + + if (type == RMAP_OSPF) + { + tag = rule; + ei = object; + + return ((ei->tag == *tag)? RMAP_MATCH : RMAP_NOMATCH); + } + + return RMAP_NOMATCH; +} + +/* Route map `match tag' match statement. `arg' is TAG value */ +static void * +route_match_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's compiled 'match tag' value. */ +static void +route_match_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag matching. */ +struct route_map_rule_cmd route_match_tag_cmd = +{ + "tag", + route_match_tag, + route_match_tag_compile, + route_match_tag_free, +}; + + /* `set metric METRIC' */ /* Set metric to attribute. */ static route_map_result_t @@ -445,6 +506,21 @@ route_set_metric_compile (const char *arg) u_int32_t *metric; int32_t ret; + /* OSPF doesn't support the +/- in + set metric <+/-metric> check + Ignore the +/- component */ + if (! all_digit (arg)) + { + if ((strncmp (arg, "+", 1) == 0 || strncmp (arg, "-", 1) == 0) && + all_digit (arg+1)) + { + zlog_warn ("OSPF does not support 'set metric +/-'"); + arg++; + } + else + return NULL; + } + metric = XCALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t)); ret = atoi (arg); @@ -531,6 +607,67 @@ struct route_map_rule_cmd route_set_metric_type_cmd = route_set_metric_type_free, }; +static route_map_result_t +route_set_tag (void *rule, struct prefix *prefix, + route_map_object_t type, void *object) +{ + u_short *tag; + struct external_info *ei; + + if (type == RMAP_OSPF) + { + tag = rule; + ei = object; + + /* Set tag value */ + ei->tag=*tag; + } + + return RMAP_OKAY; +} + +/* Route map `tag' compile function. Given string is converted to u_short. */ +static void * +route_set_tag_compile (const char *arg) +{ + u_short *tag; + u_short tmp; + + /* tag value shoud be integer. */ + if (! all_digit (arg)) + return NULL; + + tmp = atoi(arg); + + if (tmp < 1) + return NULL; + + tag = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_short)); + + if (!tag) + return tag; + + *tag = tmp; + + return tag; +} + +/* Free route map's tag value. */ +static void +route_set_tag_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Route map commands for tag set. */ +struct route_map_rule_cmd route_set_tag_cmd = +{ + "tag", + route_set_tag, + route_set_tag_compile, + route_set_tag_free, +}; + DEFUN (match_ip_nexthop, match_ip_nexthop_cmd, "match ip next-hop (<1-199>|<1300-2699>|WORD)", @@ -716,6 +853,37 @@ ALIAS (no_match_interface, "Match first hop interface of route\n" "Interface name\n") +DEFUN (match_tag, + match_tag_cmd, + "match tag <1-65535>", + MATCH_STR + "Match tag of route\n" + "Tag value\n") +{ + return ospf_route_match_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_match_tag, + no_match_tag_cmd, + "no match tag", + NO_STR + MATCH_STR + "Match tag of route\n") +{ + if (argc == 0) + return ospf_route_match_delete (vty, vty->index, "tag", NULL); + + return ospf_route_match_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_match_tag, + no_match_tag_val_cmd, + "no match tag <1-65535>", + NO_STR + MATCH_STR + "Match tag of route\n" + "Tag value\n") + DEFUN (set_metric, set_metric_cmd, "set metric <0-4294967295>", @@ -785,6 +953,37 @@ ALIAS (no_set_metric_type, "OSPF[6] external type 1 metric\n" "OSPF[6] external type 2 metric\n") +DEFUN (set_tag, + set_tag_cmd, + "set tag <1-65535>", + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") +{ + return ospf_route_set_add (vty, vty->index, "tag", argv[0]); +} + +DEFUN (no_set_tag, + no_set_tag_cmd, + "no set tag", + NO_STR + SET_STR + "Tag value for routing protocol\n") +{ + if (argc == 0) + ospf_route_set_delete(vty, vty->index, "tag", NULL); + + return ospf_route_set_delete (vty, vty->index, "tag", argv[0]); +} + +ALIAS (no_set_tag, + no_set_tag_val_cmd, + "no set tag <1-65535>", + NO_STR + SET_STR + "Tag value for routing protocol\n" + "Tag value\n") + /* Route-map init */ void ospf_route_map_init (void) @@ -801,9 +1000,11 @@ ospf_route_map_init (void) route_map_install_match (&route_match_ip_address_cmd); route_map_install_match (&route_match_ip_address_prefix_list_cmd); route_map_install_match (&route_match_interface_cmd); + route_map_install_match (&route_match_tag_cmd); route_map_install_set (&route_set_metric_cmd); route_map_install_set (&route_set_metric_type_cmd); + route_map_install_set (&route_set_tag_cmd); install_element (RMAP_NODE, &match_ip_nexthop_cmd); install_element (RMAP_NODE, &no_match_ip_nexthop_cmd); @@ -820,6 +1021,9 @@ ospf_route_map_init (void) install_element (RMAP_NODE, &match_interface_cmd); install_element (RMAP_NODE, &no_match_interface_cmd); install_element (RMAP_NODE, &no_match_interface_val_cmd); + install_element (RMAP_NODE, &match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_cmd); + install_element (RMAP_NODE, &no_match_tag_val_cmd); install_element (RMAP_NODE, &set_metric_cmd); install_element (RMAP_NODE, &no_set_metric_cmd); @@ -827,4 +1031,7 @@ ospf_route_map_init (void) install_element (RMAP_NODE, &set_metric_type_cmd); install_element (RMAP_NODE, &no_set_metric_type_cmd); install_element (RMAP_NODE, &no_set_metric_type_val_cmd); + install_element (RMAP_NODE, &set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_cmd); + install_element (RMAP_NODE, &no_set_tag_val_cmd); } diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 58a39921..2806c1a0 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -837,13 +837,6 @@ ospf_spf_next (struct vertex *v, struct ospf_area *area, if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB) continue; - /* Infinite distance links shouldn't be followed, except - * for local links (a stub-routed router still wants to - * calculate tree, so must follow its own links). - */ - if ((v != area->spf) && l->m[0].metric >= OSPF_OUTPUT_COST_INFINITE) - continue; - /* (b) Otherwise, W is a transit vertex (router or transit network). Look up the vertex W's LSA (router-LSA or network-LSA) in Area A's link state database. */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index fb17dff3..a49fdfce 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2655,6 +2655,52 @@ DEFUN (no_ospf_auto_cost_reference_bandwidth, return CMD_SUCCESS; } +DEFUN (ospf_write_multiplier, + ospf_write_multiplier_cmd, + "ospf write-multiplier <1-100>", + "OSPF specific commands\n" + "Write multiplier\n" + "Maximum number of interface serviced per write\n") +{ + struct ospf *ospf = vty->index; + u_int32_t write_oi_count; + + write_oi_count = strtol (argv[0], NULL, 10); + if (write_oi_count < 1 || write_oi_count > 100) + { + vty_out (vty, "write-multiplier value is invalid%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ospf->write_oi_count = write_oi_count; + return CMD_SUCCESS; +} + +ALIAS (ospf_write_multiplier, + write_multiplier_cmd, + "write-multiplier <1-100>", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") + +DEFUN (no_ospf_write_multiplier, + no_ospf_write_multiplier_cmd, + "no ospf write-multiplier", + NO_STR + "OSPF specific commands\n" + "Write multiplier\n") +{ + struct ospf *ospf = vty->index; + + ospf->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; + return CMD_SUCCESS; +} + +ALIAS (no_ospf_write_multiplier, + no_write_multiplier_cmd, + "no write-multiplier", + NO_STR + "Write multiplier\n") + const char *ospf_abr_type_descr_str[] = { "Unknown", @@ -2878,6 +2924,10 @@ DEFUN (show_ip_ospf, ospf_timer_dump (ospf->t_spf_calc, timebuf, sizeof (timebuf)), VTY_NEWLINE); + /* Show write multiplier values */ + vty_out (vty, " Write Multiplier set to %d %s", + ospf->write_oi_count, VTY_NEWLINE); + /* Show refresh parameters. */ vty_out (vty, " Refresh timer %d secs%s", ospf->lsa_refresh_interval, VTY_NEWLINE); @@ -2955,30 +3005,37 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, if (oi == NULL) continue; - /* Show OSPF interface information. */ - vty_out (vty, " Internet Address %s/%d,", - inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen); - - if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK) + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) { - struct in_addr *dest; - const char *dstr; - - if (CONNECTED_PEER(oi->connected) - || oi->type == OSPF_IFTYPE_VIRTUALLINK) - dstr = "Peer"; - else - dstr = "Broadcast"; - - /* For Vlinks, showing the peer address is probably more - * informative than the local interface that is being used - */ - if (oi->type == OSPF_IFTYPE_VIRTUALLINK) - dest = &oi->vl_data->peer_addr; - else - dest = &oi->connected->destination->u.prefix4; - - vty_out (vty, " %s %s,", dstr, inet_ntoa (*dest)); + vty_out (vty, " This interface is UNNUMBERED,"); + } + else + { + /* Show OSPF interface information. */ + vty_out (vty, " Internet Address %s/%d,", + inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen); + + if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK) + { + struct in_addr *dest; + const char *dstr; + + if (CONNECTED_PEER(oi->connected) + || oi->type == OSPF_IFTYPE_VIRTUALLINK) + dstr = "Peer"; + else + dstr = "Broadcast"; + + /* For Vlinks, showing the peer address is probably more + * informative than the local interface that is being used + */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) + dest = &oi->vl_data->peer_addr; + else + dest = &oi->connected->destination->u.prefix4; + + vty_out (vty, " %s %s,", dstr, inet_ntoa (*dest)); + } } vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area), @@ -3030,7 +3087,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE); } } - + /* Next network-LSA sequence number we'll use, if we're elected DR */ if (oi->params && ntohl (oi->params->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER) @@ -3117,7 +3174,7 @@ DEFUN (show_ip_ospf_interface, static void show_ip_ospf_neighbour_header (struct vty *vty) { - vty_out (vty, "%s%15s %3s %-15s %9s %-15s %-20s %5s %5s %5s%s", + vty_out (vty, "%s%-15s %3s %-15s %9s %-15s %-20s %5s %5s %5s%s", VTY_NEWLINE, "Neighbor ID", "Pri", "State", "Dead Time", "Address", "Interface", "RXmtL", "RqstL", "DBsmL", @@ -5184,11 +5241,12 @@ ALIAS (ip_ospf_dead_interval_minimal, DEFUN (no_ip_ospf_dead_interval, no_ip_ospf_dead_interval_addr_cmd, - "no ip ospf dead-interval A.B.C.D", + "no ip ospf dead-interval <1-65535> A.B.C.D", NO_STR "IP Information\n" "OSPF interface commands\n" "Interval after which a neighbor is declared dead\n" + "Seconds\n" "Address of interface") { struct interface *ifp = vty->index; @@ -5201,9 +5259,9 @@ DEFUN (no_ip_ospf_dead_interval, ifp = vty->index; params = IF_DEF_PARAMS (ifp); - if (argc == 1) + if (argc == 2) { - ret = inet_aton(argv[0], &addr); + ret = inet_aton(argv[1], &addr); if (!ret) { vty_out (vty, "Please specify interface address by A.B.C.D%s", @@ -5251,6 +5309,15 @@ DEFUN (no_ip_ospf_dead_interval, } ALIAS (no_ip_ospf_dead_interval, + no_ip_ospf_dead_interval_seconds_cmd, + "no ip ospf dead-interval <1-65535>", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Interval after which a neighbor is declared dead\n" + "Seconds\n") + +ALIAS (no_ip_ospf_dead_interval, no_ip_ospf_dead_interval_cmd, "no ip ospf dead-interval", NO_STR @@ -5328,11 +5395,12 @@ ALIAS (ip_ospf_hello_interval, DEFUN (no_ip_ospf_hello_interval, no_ip_ospf_hello_interval_addr_cmd, - "no ip ospf hello-interval A.B.C.D", + "no ip ospf hello-interval <1-65535> A.B.C.D", NO_STR "IP Information\n" "OSPF interface commands\n" "Time between HELLO packets\n" + "Seconds\n" "Address of interface") { struct interface *ifp = vty->index; @@ -5343,9 +5411,9 @@ DEFUN (no_ip_ospf_hello_interval, ifp = vty->index; params = IF_DEF_PARAMS (ifp); - if (argc == 1) + if (argc == 2) { - ret = inet_aton(argv[0], &addr); + ret = inet_aton(argv[1], &addr); if (!ret) { vty_out (vty, "Please specify interface address by A.B.C.D%s", @@ -5371,6 +5439,15 @@ DEFUN (no_ip_ospf_hello_interval, } ALIAS (no_ip_ospf_hello_interval, + no_ip_ospf_hello_interval_seconds_cmd, + "no ip ospf hello-interval <1-65535>", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Time between HELLO packets\n" + "Seconds\n") + +ALIAS (no_ip_ospf_hello_interval, no_ip_ospf_hello_interval_cmd, "no ip ospf hello-interval", NO_STR @@ -6525,7 +6602,7 @@ DEFUN (no_ospf_max_metric_router_lsa_startup, DEFUN (ospf_max_metric_router_lsa_shutdown, ospf_max_metric_router_lsa_shutdown_cmd, - "max-metric router-lsa on-shutdown <5-86400>", + "max-metric router-lsa on-shutdown <5-100>", "OSPF maximum / infinite-distance metric\n" "Advertise own Router-LSA with infinite distance (stub router)\n" "Advertise stub-router prior to full shutdown of OSPF\n" @@ -7454,6 +7531,11 @@ ospf_config_write (struct vty *vty) ospf->spf_delay, ospf->spf_holdtime, ospf->spf_max_holdtime, VTY_NEWLINE); + /* Write multiplier print. */ + if (ospf->write_oi_count != OSPF_WRITE_INTERFACE_COUNT_DEFAULT) + vty_out (vty, " ospf write-multiplier %d%s", + ospf->write_oi_count, VTY_NEWLINE); + /* Max-metric router-lsa print */ config_write_stub_router (vty, ospf); @@ -7637,12 +7719,14 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &ip_ospf_dead_interval_minimal_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_dead_interval_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_dead_interval_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_dead_interval_seconds_cmd); /* "ip ospf hello-interval" commands. */ install_element (INTERFACE_NODE, &ip_ospf_hello_interval_addr_cmd); install_element (INTERFACE_NODE, &ip_ospf_hello_interval_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_hello_interval_addr_cmd); install_element (INTERFACE_NODE, &no_ip_ospf_hello_interval_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_hello_interval_seconds_cmd); /* "ip ospf network" commands. */ install_element (INTERFACE_NODE, &ip_ospf_network_cmd); @@ -7730,6 +7814,51 @@ static struct cmd_node ospf_node = 1 }; +static void +ospf_interface_clear (struct interface *ifp) +{ + if (!if_is_operative (ifp)) return; + + if (IS_DEBUG_OSPF (ism, ISM_EVENTS)) + zlog (NULL, LOG_DEBUG, "ISM[%s]: clear by reset", ifp->name); + + ospf_if_reset(ifp); +} + +DEFUN (clear_ip_ospf_interface, + clear_ip_ospf_interface_cmd, + "clear ip ospf interface [IFNAME]", + CLEAR_STR + IP_STR + "OSPF information\n" + "Interface information\n" + "Interface name\n") +{ + struct interface *ifp; + struct listnode *node; + + if (argc == 0) /* Clear all the ospfv2 interfaces. */ + { + for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + ospf_interface_clear(ifp); + } + else /* Interface name is specified. */ + { + if ((ifp = if_lookup_by_name (argv[0])) == NULL) + vty_out (vty, "No such interface name%s", VTY_NEWLINE); + else + ospf_interface_clear(ifp); + } + + return CMD_SUCCESS; +} + +void +ospf_vty_clear_init (void) +{ + install_element (ENABLE_NODE, &clear_ip_ospf_interface_cmd); +} + /* Install OSPF related vty commands. */ void @@ -7898,6 +8027,12 @@ ospf_vty_init (void) install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd); install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd); + /* write multiplier commands */ + install_element (OSPF_NODE, &ospf_write_multiplier_cmd); + install_element (OSPF_NODE, &no_ospf_write_multiplier_cmd); + install_element (OSPF_NODE, &write_multiplier_cmd); + install_element (OSPF_NODE, &no_write_multiplier_cmd); + /* Init interface related vty commands. */ ospf_vty_if_init (); diff --git a/ospfd/ospf_vty.h b/ospfd/ospf_vty.h index da0ed1cc..28bb419a 100644 --- a/ospfd/ospf_vty.h +++ b/ospfd/ospf_vty.h @@ -53,5 +53,6 @@ /* Prototypes. */ extern void ospf_vty_init (void); extern void ospf_vty_show_init (void); +extern void ospf_vty_clear_init (void); #endif /* _QUAGGA_OSPF_VTY_H */ diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 89404552..a4aae87f 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -351,6 +351,12 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) if (distance) SET_FLAG (message, ZAPI_MESSAGE_DISTANCE); + /* Check if path type is ASE and use only 16bit tags */ + if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL) || + (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)) && + (or->u.ext.tag > 0) && (or->u.ext.tag < UINT16_MAX)) + SET_FLAG (message, ZAPI_MESSAGE_TAG); + /* Make packet. */ s = zclient->obuf; stream_reset (s); @@ -397,12 +403,13 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE)) { char buf[2][INET_ADDRSTRLEN]; - zlog_debug("Zebra: Route add %s/%d nexthop %s", + zlog_debug("Zebra: Route add %s/%d nexthop %s, ifindex=%d", inet_ntop(AF_INET, &p->prefix, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, &path->nexthop, - buf[1], sizeof(buf[1]))); + buf[1], sizeof(buf[1])), + path->ifindex); } } @@ -418,6 +425,9 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) stream_putl (s, or->cost); } + if (CHECK_FLAG (message, ZAPI_MESSAGE_TAG)) + stream_putw (s, (u_short)or->u.ext.tag); + stream_putw_at (s, 0, stream_get_endp (s)); zclient_send_message(zclient); @@ -526,6 +536,7 @@ ospf_zebra_add_discard (struct prefix_ipv4 *p) SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; + api.tag = 0; zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, p, &api); @@ -550,6 +561,7 @@ ospf_zebra_delete_discard (struct prefix_ipv4 *p) SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 0; api.ifindex_num = 0; + api.tag = 0; zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api); @@ -869,6 +881,10 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, api.distance = stream_getc (s); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) + api.tag = stream_getw (s); + else + api.tag = 0; ospf = ospf_lookup (); if (ospf == NULL) @@ -886,8 +902,12 @@ ospf_zebra_read_ipv4 (int command, struct zclient *zclient, * || CHECK_FLAG (api.flags, ZEBRA_FLAG_REJECT)) * return 0; */ - - ei = ospf_external_info_add (api.type, p, ifindex, nexthop); + + /* Protocol tag overwrites all other tag value send by zebra */ + if (ospf->dtag[api.type] > 0) + api.tag = ospf->dtag[api.type]; + + ei = ospf_external_info_add (api.type, p, ifindex, nexthop, api.tag); if (ospf->router_id.s_addr == 0) /* Set flags to generate AS-external-LSA originate event diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index c9fcdc39..36ace1e5 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -197,6 +197,7 @@ ospf_new (void) { new->dmetric[i].type = -1; new->dmetric[i].value = -1; + new->dtag[i] = 0; } new->default_metric = -1; new->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; @@ -245,6 +246,7 @@ ospf_new (void) } new->t_read = thread_add_read (master, ospf_read, new, new->fd); new->oi_write_q = list_new (); + new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; return new; } diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index 098fc5f4..c5f7fa14 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -214,6 +214,8 @@ struct ospf struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/ struct thread *t_write; +#define OSPF_WRITE_INTERFACE_COUNT_DEFAULT 20 + int write_oi_count; /* Num of packets sent per thread invocation */ struct thread *t_read; int fd; unsigned int maxsndbuflen; @@ -237,6 +239,9 @@ struct ospf -1 means metric value is not set. */ } dmetric [ZEBRA_ROUTE_MAX + 1]; + /* Redistribute tag info. */ + u_short dtag [ZEBRA_ROUTE_MAX + 1]; + /* For redistribute route map. */ struct { @@ -299,10 +304,6 @@ struct ospf_area /* Configured variables. */ int external_routing; /* ExternalRoutingCapability. */ -#define OSPF_AREA_DEFAULT 0 -#define OSPF_AREA_STUB 1 -#define OSPF_AREA_NSSA 2 -#define OSPF_AREA_TYPE_MAX 3 int no_summary; /* Don't inject summaries into stub.*/ int shortcut_configured; /* Area configured as shortcut. */ #define OSPF_SHORTCUT_DEFAULT 0 |