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. */
- SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
- ospf_if_set_multicast(oi);
- }
- return;
- }
-
/* get neighbor prefix. */
p.family = AF_INET;
p.prefixlen = ip_masklen (hello->network_mask);
&& oi->type != OSPF_IFTYPE_VIRTUALLINK)
if (oi->address->prefixlen != p.prefixlen)
{
- zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
- inet_ntoa (ospfh->router_id));
+ zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch on %s (configured prefix length is %d, but hello packet indicates %d).",
+ inet_ntoa(ospfh->router_id), IF_NAME(oi),
+ (int)oi->address->prefixlen, (int)p.prefixlen);
return;
}
/* 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 */
if (IS_SET_DD_MS (nbr->dd_flags))
{
nbr->dd_seqnum++;
- /* Entire DD packet sent. */
+
+ /* Both sides have no More, then we're done with Exchange */
if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
else
- /* Send new DD packet. */
ospf_db_desc_send (nbr);
}
/* Slave */
{
nbr->dd_seqnum = ntohl (dd->dd_seqnum);
- /* When master's more flags is not set. */
- if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))
- {
- nbr->dd_flags &= ~(OSPF_DD_FLAG_M);
- OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
- }
-
- /* Send DD packet in reply. */
+ /* Send DD packet in reply.
+ *
+ * Must be done to acknowledge the Master's DD, regardless of
+ * whether we have more LSAs ourselves to describe.
+ *
+ * This function will clear the 'More' bit, if after this DD
+ * we have no more LSAs to describe to the master..
+ */
ospf_db_desc_send (nbr);
+
+ /* Slave can raise ExchangeDone now, if master is also done */
+ if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);
}
-
+
/* Save received neighbor values from DD. */
ospf_db_desc_save_current (nbr, dd);
}
}
#endif /* HAVE_OPAQUE_LSA */
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Process DD packet by neighbor status. */
switch (nbr->state)
{
zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Slave).",
inet_ntoa(nbr->router_id));
nbr->dd_seqnum = ntohl (dd->dd_seqnum);
- nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */
+
+ /* Reset I/MS */
+ UNSET_FLAG (nbr->dd_flags, (OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I));
}
else
{
{
zlog_info ("Packet[DD]: Neighbor %s Negotiation done (Master).",
inet_ntoa(nbr->router_id));
- nbr->dd_flags &= ~OSPF_DD_FLAG_I;
+ /* Reset I, leaving MS */
+ UNSET_FLAG (nbr->dd_flags, OSPF_DD_FLAG_I);
}
else
{
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);
/* Check authentication. */
if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
{
- zlog_warn ("interface %s: ospf_read authentication type mismatch.",
- IF_NAME (oi));
+ zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
+ IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
return -1;
}
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
{
if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
{
- zlog_debug ("Packet from [%s] received on link %s"
- " but no ospf_interface",
- inet_ntoa (iph->ip_src), ifp->name);
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("Packet from [%s] received on link %s"
+ " but no ospf_interface",
+ inet_ntoa (iph->ip_src), ifp->name);
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)
ifp->name, if_flag_dump(ifp->flags));
/* Fix multicast memberships? */
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
- SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
+ OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
else if (iph->ip_dst.s_addr == htonl(OSPF_ALLDROUTERS))
- SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+ OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
if (oi->multicast_memberships)
ospf_if_set_multicast(oi);
return 0;
#endif /* HAVE_OPAQUE_LSA */
stream_putc (s, options);
- /* Keep pointer to flags. */
+ /* DD flags */
pp = stream_get_endp (s);
stream_putc (s, nbr->dd_flags);
/* Set DD Sequence Number. */
stream_putl (s, nbr->dd_seqnum);
+ /* shortcut unneeded walk of (empty) summary LSDBs */
if (ospf_db_summary_isempty (nbr))
- {
- if (nbr->state >= NSM_Exchange)
- {
- nbr->dd_flags &= ~OSPF_DD_FLAG_M;
- /* Set DD flags again */
- stream_putc_at (s, pp, 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))
+ {
+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;
}
stream_put_ipv4 (s, lsa->data->id.s_addr);
stream_put_ipv4 (s, lsa->data->adv_router.s_addr);
- ospf_lsa_unlock (nbr->ls_req_last);
+ ospf_lsa_unlock (&nbr->ls_req_last);
nbr->ls_req_last = ospf_lsa_lock (lsa);
*length += 12;
{
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);
count++;
list_delete_node (update, node);
- ospf_lsa_unlock (lsa);
+ ospf_lsa_unlock (&lsa); /* oi->ls_upd_queue */
}
/* Now set #LSAs. */
static int
ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
{
- struct list *rm_list;
- struct listnode *node;
+ struct listnode *node, *nnode;
u_int16_t length = OSPF_LS_ACK_MIN_SIZE;
unsigned long delta = stream_get_endp(s) + 24;
struct ospf_lsa *lsa;
- rm_list = list_new ();
-
- for (ALL_LIST_ELEMENTS_RO (ack, node, lsa))
+ for (ALL_LIST_ELEMENTS (ack, node, nnode, lsa))
{
- lsa = listgetdata (node);
assert (lsa);
if (length + delta > ospf_packet_max (oi))
stream_put (s, lsa->data, OSPF_LSA_HEADER_SIZE);
length += OSPF_LSA_HEADER_SIZE;
- listnode_add (rm_list, lsa);
- }
-
- /* Remove LSA from LS-Ack list. */
- /* XXX: this loop should be removed and the list move done in previous
- * loop
- */
- for (ALL_LIST_ELEMENTS_RO (rm_list, node, lsa))
- {
listnode_delete (ack, lsa);
- ospf_lsa_unlock (lsa);
+ ospf_lsa_unlock (&lsa); /* oi->ls_ack_direct.ls_ack */
}
- list_delete (rm_list);
-
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
rn->info = list_new ();
for (ALL_LIST_ELEMENTS_RO (update, node, lsa))
- {
- ospf_lsa_lock (lsa);
- listnode_add (rn->info, lsa);
- }
+ listnode_add (rn->info, ospf_lsa_lock (lsa)); /* oi->ls_upd_queue */
if (oi->t_ls_upd_event == NULL)
oi->t_ls_upd_event =