summaryrefslogtreecommitdiffstats
path: root/ospfd
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/ospf_abr.h1
-rw-r--r--ospfd/ospf_asbr.c5
-rw-r--r--ospfd/ospf_asbr.h3
-rw-r--r--ospfd/ospf_dump.c2
-rw-r--r--ospfd/ospf_interface.c18
-rw-r--r--ospfd/ospf_lsa.c45
-rw-r--r--ospfd/ospf_main.c1
-rw-r--r--ospfd/ospf_network.c36
-rw-r--r--ospfd/ospf_nsm.c3
-rw-r--r--ospfd/ospf_packet.c267
-rw-r--r--ospfd/ospf_route.c2
-rw-r--r--ospfd/ospf_routemap.c223
-rw-r--r--ospfd/ospf_spf.c7
-rw-r--r--ospfd/ospf_vty.c199
-rw-r--r--ospfd/ospf_vty.h1
-rw-r--r--ospfd/ospf_zebra.c28
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--ospfd/ospfd.h9
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