fifo->count++;
}
+/* Add new packet to head of fifo. */
+static void
+ospf_fifo_push_head (struct ospf_fifo *fifo, struct ospf_packet *op)
+{
+ op->next = fifo->head;
+
+ if (fifo->tail == NULL)
+ fifo->tail = op;
+
+ fifo->head = op;
+
+ fifo->count++;
+}
+
/* Delete first packet from fifo. */
struct ospf_packet *
ospf_fifo_pop (struct ospf_fifo *fifo)
/* ospf_fifo_debug (oi->obuf); */
}
+static void
+ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
+{
+ if (!oi->obuf)
+ {
+ zlog_err("ospf_packet_add(interface %s in state %d [%s], packet type %s, "
+ "destination %s) called with NULL obuf, ignoring "
+ "(please report this bug)!\n",
+ IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
+ ospf_packet_type_str[stream_getc_from(op->s, 1)],
+ inet_ntoa (op->dst));
+ return;
+ }
+
+ /* Add packet to head of queue. */
+ ospf_fifo_push_head (oi->obuf, op);
+
+ /* Debug of packet fifo*/
+ /* ospf_fifo_debug (oi->obuf); */
+}
+
void
ospf_packet_delete (struct ospf_interface *oi)
{
struct ospf_packet *new;
if (stream_get_endp(op->s) != op->length)
- zlog_warn ("ospf_packet_dup stream %ld ospf_packet %d size mismatch",
- STREAM_SIZE(op->s), op->length);
+ /* XXX size_t */
+ zlog_warn ("ospf_packet_dup stream %lu ospf_packet %u size mismatch",
+ (u_long)STREAM_SIZE(op->s), op->length);
/* Reserve space for MD5 authentication that may be added later. */
new = ospf_packet_new (stream_get_endp(op->s) + OSPF_AUTH_MD5_SIZE);
return 0;
/* We do this here so when we dup a packet, we don't have to
- waste CPU rewriting other headers. */
+ waste CPU rewriting other headers.
+
+ Note that quagga_time /deliberately/ is not used here */
t = (time(NULL) & 0xFFFFFFFF);
if (t > oi->crypt_seqnum)
oi->crypt_seqnum = t;
op->length = ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE;
if (stream_get_endp(op->s) != op->length)
- zlog_warn("ospf_make_md5_digest: length mismatch stream %ld ospf_packet %d", stream_get_endp(op->s), op->length);
+ /* XXX size_t */
+ zlog_warn("ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
+ (u_long)stream_get_endp(op->s), op->length);
return OSPF_AUTH_MD5_SIZE;
}
fired. This is a small tweak to what is in the RFC,
but it will cut out out a lot of retransmit traffic
- MAG */
- if (tv_cmp (tv_sub (recent_time, lsa->tv_recv),
+ if (tv_cmp (tv_sub (recent_relative_time (), lsa->tv_recv),
int2tv (retransmit_interval)) >= 0)
listnode_add (update, rn->info);
}
ipid = (time(NULL) & 0xffff);
#endif /* WANT_OSPF_WRITE_FRAGMENT */
- /* convenience - max OSPF data per packet */
- maxdatasize = oi->ifp->mtu - sizeof (struct ip);
+ /* 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);
/* Get one packet from queue. */
op = ospf_fifo_head (oi->obuf);
memset (&sa_dst, 0, sizeof (sa_dst));
sa_dst.sin_family = AF_INET;
-#ifdef HAVE_SIN_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sa_dst.sin_len = sizeof(sa_dst);
-#endif /* HAVE_SIN_LEN */
+#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
sa_dst.sin_addr = op->dst;
sa_dst.sin_port = htons (0);
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);
+#endif
+
#ifdef WANT_OSPF_WRITE_FRAGMENT
/* XXX-MT: not thread-safe at all..
* XXX: this presumes this is only programme sending OSPF packets
return;
}
- /* If incoming interface is passive one, ignore Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) {
- char buf[3][INET_ADDRSTRLEN];
- zlog_debug ("ignoring HELLO from router %s sent to %s, "
- "received on a passive interface, %s",
- inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
- inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
- inet_ntop(AF_INET, &oi->address->u.prefix4,
- buf[2], sizeof(buf[2])));
- if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
- {
- /* Try to fix multicast membership. */
- OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
- ospf_if_set_multicast(oi);
- }
- return;
- }
-
/* get neighbor prefix. */
p.family = AF_INET;
p.prefixlen = ip_masklen (hello->network_mask);
/* Compare Router Dead Interval. */
if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval))
{
- zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch "
+ "(expected %u, but received %u).",
+ inet_ntoa(ospfh->router_id),
+ OSPF_IF_PARAM(oi, v_wait), ntohl(hello->dead_interval));
return;
}
{
if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval))
{
- zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch "
+ "(expected %u, but received %u).",
+ inet_ntoa(ospfh->router_id),
+ OSPF_IF_PARAM(oi, v_hello), ntohs(hello->hello_interval));
return;
}
}
old_state = nbr->state;
/* Add event to thread. */
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
/* RFC2328 Section 9.5.1
If the router is not eligible to become Designated Router,
if (oi->type == OSPF_IFTYPE_NBMA &&
(old_state == NSM_Down || old_state == NSM_Attempt))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
nbr->priority = hello->priority;
nbr->d_router = hello->d_router;
nbr->bd_router = hello->bd_router;
if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors,
size - OSPF_HELLO_MIN_SIZE))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_TwoWayReceived);
nbr->options |= hello->options;
}
else
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
/* Set neighbor information. */
nbr->priority = hello->priority;
nbr->d_router = hello->d_router;
/* Lookup received LSA, then add LS request list. */
find = ospf_lsa_lookup_by_header (oi->area, lsah);
- if (!find || ospf_lsa_more_recent (find, new) < 0)
- {
- ospf_ls_request_add (nbr, new);
- ospf_lsa_discard (new);
- }
- else
- {
- /* Received LSA is not recent. */
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
- "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
- ospf_lsa_discard (new);
- continue;
- }
+
+ /* ospf_lsa_more_recent is fine with NULL pointers */
+ switch (ospf_lsa_more_recent (find, new))
+ {
+ case -1:
+ /* Neighbour has a more recent LSA, we must request it */
+ ospf_ls_request_add (nbr, new);
+ case 0:
+ /* If we have a copy of this LSA, it's either less recent
+ * and we're requesting it from neighbour (the case above), or
+ * it's as recent and we both have same copy (this case).
+ *
+ * In neither of these two cases is there any point in
+ * describing our copy of the LSA to the neighbour in a
+ * DB-Summary packet, if we're still intending to do so.
+ *
+ * See: draft-ogier-ospf-dbex-opt-00.txt, describing the
+ * backward compatible optimisation to OSPF DB Exchange /
+ * DB Description process implemented here.
+ */
+ if (find)
+ ospf_lsdb_delete (&nbr->db_sum, find);
+ ospf_lsa_discard (new);
+ break;
+ default:
+ /* We have the more recent copy, nothing specific to do:
+ * - no need to request neighbours stale copy
+ * - must leave DB summary list copy alone
+ */
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("Packet [DD:RECV]: LSA received Type %d, "
+ "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));
+ ospf_lsa_discard (new);
+ }
}
/* Master */
}
#endif /* HAVE_OPAQUE_LSA */
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Process DD packet by neighbor status. */
switch (nbr->state)
{
else
{
struct timeval t, now;
- gettimeofday (&now, NULL);
+ quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
t = tv_sub (now, nbr->last_send_ts);
if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)
{
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Neighbor State should be Exchange or later. */
if (nbr->state != NSM_Exchange &&
nbr->state != NSM_Loading &&
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Check neighbor state. */
if (nbr->state < NSM_Exchange)
{
/* Reject from STUB or NSSA */
if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)
{
- DISCARD_LSA (lsa, 1);
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("Incoming External LSA Discarded: We are NSSA/STUB Area");
+ DISCARD_LSA (lsa, 1);
}
if (lsa->data->type == OSPF_AS_NSSA_LSA)
if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)
{
- DISCARD_LSA (lsa,2);
if (IS_DEBUG_OSPF_NSSA)
zlog_debug("Incoming NSSA LSA Discarded: Not NSSA Area");
+ DISCARD_LSA (lsa,2);
}
/* Find the LSA in the current database. */
{
struct timeval now;
- gettimeofday (&now, NULL);
+ quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
if (tv_cmp (tv_sub (now, current->tv_orig),
- int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)
+ int2tv (OSPF_MIN_LS_ARRIVAL)) >= 0)
/* Trap NSSA type later.*/
ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);
DISCARD_LSA (lsa, 8);
}
}
}
-
+#undef DISCARD_LSA
+
assert (listcount (lsas) == 0);
list_delete (lsas);
}
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
if (nbr->state < NSM_Exchange)
{
zlog_warn ("Link State Acknowledgment: "
ip_len = ip_len + (iph->ip_hl << 2);
#endif
+#if defined(__DragonFly__)
+ /*
+ * in DragonFly's raw socket, ip_len/ip_off are read
+ * in network byte order.
+ * As OpenBSD < 200311 adjust ip_len to strip IP header size!
+ */
+ ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
+#endif
+
ifindex = getsockopt_ifindex (AF_INET, &msgh);
*ifp = if_lookup_by_index (ifindex);
ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
/* associate packet with ospf interface */
- oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
+ oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
+
+ /* If incoming interface is passive one, ignore it. */
+ if (oi && OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
+ {
+ char buf[3][INET_ADDRSTRLEN];
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("ignoring packet from router %s sent to %s, "
+ "received on a passive interface, %s",
+ inet_ntop(AF_INET, &ospfh->router_id, buf[0], sizeof(buf[0])),
+ inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
+ inet_ntop(AF_INET, &oi->address->u.prefix4,
+ buf[2], sizeof(buf[2])));
+
+ if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
+ {
+ /* Try to fix multicast membership.
+ * Some OS:es may have problems in this area,
+ * make sure it is removed.
+ */
+ OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
+ ospf_if_set_multicast(oi);
+ }
+ return 0;
+ }
+
/* if no local ospf_interface,
* or header area is backbone but ospf_interface is not
return 0;
}
}
-
+
/* else it must be a local ospf interface, check it was received on
* correct link
*/
else if (oi->ifp != ifp)
{
- zlog_warn ("Packet from [%s] received on wrong link %s",
- inet_ntoa (iph->ip_src), ifp->name);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_warn ("Packet from [%s] received on wrong link %s",
+ inet_ntoa (iph->ip_src), ifp->name);
return 0;
}
else if (oi->state == ISM_Down)
/* Set DD Sequence Number. */
stream_putl (s, nbr->dd_seqnum);
+ /* shortcut unneeded walk of (empty) summary LSDBs */
if (ospf_db_summary_isempty (nbr))
- {
- /* Sanity check:
- *
- * Must be here either:
- * - Initial DBD (ospf_nsm.c)
- * - M must be set
- * or
- * - finishing Exchange, and DB-Summary list empty
- * - from ospf_db_desc_proc()
- * - M must not be set
- */
- if (nbr->state >= NSM_Exchange)
- assert (!IS_SET_DD_M(nbr->dd_flags));
- else
- assert (IS_SET_DD_M(nbr->dd_flags));
-
- return length;
- }
+ goto empty;
/* Describe LSA Header from Database Summary List. */
lsdb = &nbr->db_sum;
/* Update 'More' bit */
if (ospf_db_summary_isempty (nbr))
{
- UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
- /* Rewrite DD flags */
- stream_putc_at (s, pp, nbr->dd_flags);
+empty:
+ if (nbr->state >= NSM_Exchange)
+ {
+ UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_M);
+ /* Rewrite DD flags */
+ stream_putc_at (s, pp, nbr->dd_flags);
+ }
+ else
+ {
+ assert (IS_SET_DD_M(nbr->dd_flags));
+ }
}
return length;
}
{
struct ospf_lsa *lsa;
struct listnode *node;
- u_int16_t length = OSPF_LS_UPD_MIN_SIZE;
+ u_int16_t length = 0;
unsigned int size_noauth;
unsigned long delta = stream_get_endp (s);
unsigned long pp;
pp = stream_get_endp (s);
stream_forward_endp (s, OSPF_LS_UPD_MIN_SIZE);
+ length += OSPF_LS_UPD_MIN_SIZE;
/* Calculate amount of packet usable for data. */
size_noauth = stream_get_size(s) - ospf_packet_authspace(oi);
return length;
}
-void
-ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
+static void
+ospf_hello_send_sub (struct ospf_interface *oi, in_addr_t addr)
{
struct ospf_packet *op;
u_int16_t length = OSPF_HEADER_SIZE;
/* Set packet length. */
op->length = length;
- op->dst.s_addr = addr->s_addr;
+ op->dst.s_addr = addr;
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op);
+ /* Add packet to the top of the interface output queue, so that they
+ * can't get delayed by things like long queues of LS Update packets
+ */
+ ospf_packet_add_top (oi, op);
/* Hook thread to write packet. */
OSPF_ISM_WRITE_ON (oi->ospf);
assert(oi);
/* If this is passive interface, do not send OSPF Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
if (oi->type != OSPF_IFTYPE_NBMA)
&& oi->state != ISM_DR && oi->state != ISM_Backup)
return;
- ospf_hello_send_sub (oi, &nbr_nbma->addr);
+ ospf_hello_send_sub (oi, nbr_nbma->addr.s_addr);
}
int
zlog (NULL, LOG_DEBUG, "NSM[%s:%s]: Timer (hello-reply timer expire)",
IF_NAME (nbr->oi), inet_ntoa (nbr->router_id));
- ospf_hello_send_sub (nbr->oi, &nbr->address.u.prefix4);
+ ospf_hello_send_sub (nbr->oi, nbr->address.u.prefix4.s_addr);
return 0;
}
void
ospf_hello_send (struct ospf_interface *oi)
{
- struct ospf_packet *op;
- u_int16_t length = OSPF_HEADER_SIZE;
-
/* If this is passive interface, do not send OSPF Hello. */
- if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE)
+ if (OSPF_IF_PASSIVE_STATUS (oi) == OSPF_IF_PASSIVE)
return;
- op = ospf_packet_new (oi->ifp->mtu);
-
- /* Prepare OSPF common header. */
- ospf_make_header (OSPF_MSG_HELLO, oi, op->s);
-
- /* Prepare OSPF Hello body. */
- length += ospf_make_hello (oi, op->s);
-
- /* Fill OSPF header. */
- ospf_fill_header (oi, op->s, length);
-
- /* Set packet length. */
- op->length = length;
-
if (oi->type == OSPF_IFTYPE_NBMA)
{
struct ospf_neighbor *nbr;
if (nbr->priority == 0 && oi->state == ISM_DROther)
continue;
/* if oi->state == Waiting, send hello to all neighbors */
- {
- struct ospf_packet *op_dup;
-
- op_dup = ospf_packet_dup(op);
- op_dup->dst = nbr->address.u.prefix4;
-
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op_dup);
-
- OSPF_ISM_WRITE_ON (oi->ospf);
- }
-
+ ospf_hello_send_sub (oi, nbr->address.u.prefix4.s_addr);
}
- ospf_packet_free (op);
}
else
{
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
- op->dst.s_addr = oi->vl_data->peer_addr.s_addr;
- else
- op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
-
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op);
-
- /* Hook thread to write packet. */
- OSPF_ISM_WRITE_ON (oi->ospf);
+ ospf_hello_send_sub (oi, oi->vl_data->peer_addr.s_addr);
+ else
+ ospf_hello_send_sub (oi, htonl (OSPF_ALLSPFROUTERS));
}
}
op->length = length;
/* Decide destination address. */
- op->dst = nbr->address.u.prefix4;
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+ else
+ op->dst = nbr->address.u.prefix4;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
if (nbr->last_send)
ospf_packet_free (nbr->last_send);
nbr->last_send = ospf_packet_dup (op);
- gettimeofday (&nbr->last_send_ts, NULL);
+ quagga_gettime (QUAGGA_CLK_MONOTONIC, &nbr->last_send_ts);
}
/* Re-send Database Description. */
op->length = length;
/* Decide destination address. */
- op->dst = nbr->address.u.prefix4;
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+ else
+ op->dst = nbr->address.u.prefix4;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
else
size = oi->ifp->mtu;
- /* XXX Should this be - sizeof(struct ip)?? -gdt */
if (size > OSPF_MAX_PACKET_SIZE)
{
zlog_warn ("ospf_ls_upd_packet_new: oversized LSA id:%s too big,"
return NULL;
}
- return ospf_packet_new (size);
+ /* IP header is built up separately by ospf_write(). This means, that we must
+ * reduce the "affordable" size just calculated by length of an IP header.
+ * This makes sure, that even if we manage to fill the payload with LSA data
+ * completely, the final packet (our data plus IP header) still fits into
+ * outgoing interface MTU. This correction isn't really meaningful for an
+ * oversized LSA, but for consistency the correction is done for both cases.
+ *
+ * P.S. OSPF_MAX_PACKET_SIZE above already includes IP header size
+ */
+ return ospf_packet_new (size - sizeof (struct ip));
}
static void
op->length = length;
/* Decide destination address. */
- op->dst.s_addr = addr.s_addr;
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
+ else
+ op->dst.s_addr = addr.s_addr;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
p.prefix = oi->vl_data->peer_addr;
+ else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else if (flag == OSPF_SEND_PACKET_DIRECT)
p.prefix = nbr->address.u.prefix4;
else if (oi->state == ISM_DR || oi->state == ISM_Backup)
p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
- else if ((oi->type == OSPF_IFTYPE_POINTOPOINT)
- && (flag == OSPF_SEND_PACKET_INDIRECT))
- p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else