summaryrefslogtreecommitdiffstats
path: root/ospfd/ospf_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_packet.c')
-rw-r--r--ospfd/ospf_packet.c272
1 files changed, 141 insertions, 131 deletions
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 1066e64f..c4a6bf92 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -125,6 +125,20 @@ ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
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)
@@ -199,6 +213,27 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
/* 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)
{
@@ -324,7 +359,7 @@ static int
ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
{
struct ospf_header *ospfh;
- unsigned char digest[OSPF_AUTH_MD5_SIZE];
+ unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0};
MD5_CTX ctx;
void *ibuf;
u_int32_t t;
@@ -351,7 +386,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
/* Get MD5 Authentication key from auth_key list. */
if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
- auth_key = (const u_int8_t *) "";
+ auth_key = (const u_int8_t *) digest;
else
{
ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
@@ -745,7 +780,6 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
struct ospf_hello *hello;
struct ospf_neighbor *nbr;
int old_state;
- struct prefix p;
/* increment statistics. */
oi->hello_in++;
@@ -765,20 +799,15 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
return;
}
- /* get neighbor prefix. */
- p.family = AF_INET;
- p.prefixlen = ip_masklen (hello->network_mask);
- p.u.prefix4 = iph->ip_src;
-
/* Compare network mask. */
/* Checking is ignored for Point-to-Point and Virtual link. */
if (oi->type != OSPF_IFTYPE_POINTOPOINT
&& oi->type != OSPF_IFTYPE_VIRTUALLINK)
- if (oi->address->prefixlen != p.prefixlen)
+ if (oi->address->prefixlen != ip_masklen (hello->network_mask))
{
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);
+ (int)oi->address->prefixlen, (int)ip_masklen (hello->network_mask));
return;
}
@@ -873,7 +902,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
}
/* get neighbour struct */
- nbr = ospf_nbr_get (oi, ospfh, iph, &p);
+ nbr = ospf_nbr_get (oi, ospfh, iph);
/* neighbour must be valid, ospf_nbr_get creates if none existed */
assert (nbr);
@@ -881,7 +910,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
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,
@@ -901,58 +930,63 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
if (oi->type == OSPF_IFTYPE_NBMA &&
(old_state == NSM_Down || old_state == NSM_Attempt))
{
- OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived);
- nbr->priority = hello->priority;
- nbr->d_router = hello->d_router;
- nbr->bd_router = hello->bd_router;
- return;
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
+ goto done;
}
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);
- /* Set neighbor information. */
- nbr->priority = hello->priority;
- nbr->d_router = hello->d_router;
- nbr->bd_router = hello->bd_router;
- return;
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived);
+ goto done;
}
+ /* Neighbor priority check. */
+ if (nbr->priority >= 0 && nbr->priority != hello->priority)
+ OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+
/* If neighbor itself declares DR and no BDR exists,
cause event BackupSeen */
- if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router))
- if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting)
+ if (oi->state == ISM_Waiting &&
+ IPV4_ADDR_SAME (&nbr->src, &hello->d_router) &&
+ hello->bd_router.s_addr == 0)
+ {
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
+ goto done;
+ }
+ /* had not previously. */
+ if ((IPV4_ADDR_SAME (&nbr->src, &hello->d_router) &&
+ IPV4_ADDR_CMP (&nbr->src, &nbr->d_router)) ||
+ (IPV4_ADDR_CMP (&nbr->src, &hello->d_router) &&
+ IPV4_ADDR_SAME (&nbr->src, &nbr->d_router)))
+ {
+ OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+ goto done;
+ }
/* neighbor itself declares BDR. */
if (oi->state == ISM_Waiting &&
- IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router))
- OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
-
- /* had not previously. */
- if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) &&
- IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) ||
- (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) &&
- IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router)))
- OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
-
+ IPV4_ADDR_SAME (&nbr->src, &hello->bd_router))
+ {
+ OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen);
+ goto done;
+ }
/* had not previously. */
- if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) &&
- IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) ||
- (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) &&
- IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router)))
- OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
-
- /* Neighbor priority check. */
- if (nbr->priority >= 0 && nbr->priority != hello->priority)
- OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+ if ((IPV4_ADDR_SAME (&nbr->src, &hello->bd_router) &&
+ IPV4_ADDR_CMP (&nbr->src, &nbr->bd_router)) ||
+ (IPV4_ADDR_CMP (&nbr->src, &hello->bd_router) &&
+ IPV4_ADDR_SAME (&nbr->src, &nbr->bd_router)))
+ {
+ OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange);
+ goto done;
+ }
+ done:
/* Set neighbor information. */
nbr->priority = hello->priority;
nbr->d_router = hello->d_router;
@@ -1191,6 +1225,9 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
}
#endif /* HAVE_OPAQUE_LSA */
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Process DD packet by neighbor status. */
switch (nbr->state)
{
@@ -1260,7 +1297,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,
CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");
if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)
- && IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))
+ && IPV4_ADDR_SAME (&DR (oi), &nbr->src))
{
zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; "
"Opaque-LSAs cannot be reliably advertised "
@@ -1412,6 +1449,9 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,
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 &&
@@ -1644,6 +1684,9 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
/* Check neighbor state. */
if (nbr->state < NSM_Exchange)
{
@@ -1977,6 +2020,9 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
return;
}
+ /* Add event to thread. */
+ OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_PacketReceived);
+
if (nbr->state < NSM_Exchange)
{
zlog_warn ("Link State Acknowledgment: "
@@ -2620,7 +2666,7 @@ static int
ospf_make_hello (struct ospf_interface *oi, struct stream *s)
{
struct ospf_neighbor *nbr;
- struct route_node *rn;
+ struct listnode *node;
u_int16_t length = OSPF_HELLO_MIN_SIZE;
struct in_addr mask;
unsigned long p;
@@ -2662,10 +2708,9 @@ ospf_make_hello (struct ospf_interface *oi, struct stream *s)
stream_put_ipv4 (s, BDR (oi).s_addr);
/* Add neighbor seen. */
- for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
- if ((nbr = rn->info))
- if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */
- if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */
+ for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr))
+ if (nbr->router_id.s_addr != 0) /* Ignore 0.0.0.0 node. */
+ if (nbr->state != NSM_Attempt) /* Ignore Down neighbor. */
if (nbr->state != NSM_Down) /* This is myself for DR election. */
if (!IPV4_ADDR_SAME (&nbr->router_id, &oi->ospf->router_id))
{
@@ -2955,8 +3000,8 @@ ospf_make_ls_ack (struct ospf_interface *oi, struct list *ack, struct stream *s)
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;
@@ -2975,10 +3020,12 @@ ospf_hello_send_sub (struct ospf_interface *oi, struct in_addr *addr)
/* 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);
@@ -3009,7 +3056,7 @@ ospf_poll_send (struct ospf_nbr_nbma *nbr_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
@@ -3048,7 +3095,7 @@ ospf_hello_reply_timer (struct thread *thread)
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->src.s_addr);
return 0;
}
@@ -3057,84 +3104,48 @@ ospf_hello_reply_timer (struct thread *thread)
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_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;
- struct route_node *rn;
-
- for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
- if ((nbr = rn->info))
- if (nbr != oi->nbr_self)
- if (nbr->state != NSM_Down)
- {
- /* RFC 2328 Section 9.5.1
- If the router is not eligible to become Designated Router,
- it must periodically send Hello Packets to both the
- Designated Router and the Backup Designated Router (if they
- exist). */
- if (PRIORITY(oi) == 0 &&
- IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
- IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
- continue;
-
- /* If the router is eligible to become Designated Router, it
- must periodically send Hello Packets to all neighbors that
- are also eligible. In addition, if the router is itself the
- Designated Router or Backup Designated Router, it must also
- send periodic Hello Packets to all other neighbors. */
-
- 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;
+ struct listnode *node;
- /* Add packet to the interface output queue. */
- ospf_packet_add (oi, op_dup);
-
- OSPF_ISM_WRITE_ON (oi->ospf);
- }
-
- }
- ospf_packet_free (op);
+ for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr))
+ if (nbr != oi->nbr_self)
+ if (nbr->state != NSM_Down)
+ {
+ /* RFC 2328 Section 9.5.1
+ If the router is not eligible to become Designated Router,
+ it must periodically send Hello Packets to both the
+ Designated Router and the Backup Designated Router (if they
+ exist). */
+ if (PRIORITY(oi) == 0 &&
+ IPV4_ADDR_CMP(&DR(oi), &nbr->src) &&
+ IPV4_ADDR_CMP(&BDR(oi), &nbr->src))
+ continue;
+
+ /* If the router is eligible to become Designated Router, it
+ must periodically send Hello Packets to all neighbors that
+ are also eligible. In addition, if the router is itself the
+ Designated Router or Backup Designated Router, it must also
+ send periodic Hello Packets to all other neighbors. */
+
+ if (nbr->priority == 0 && oi->state == ISM_DROther)
+ continue;
+ /* if oi->state == Waiting, send hello to all neighbors */
+ ospf_hello_send_sub (oi, nbr->src.s_addr);
+ }
}
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));
}
}
@@ -3165,7 +3176,7 @@ ospf_db_desc_send (struct ospf_neighbor *nbr)
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
else
- op->dst = nbr->address.u.prefix4;
+ op->dst = nbr->src;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
@@ -3227,7 +3238,7 @@ ospf_ls_req_send (struct ospf_neighbor *nbr)
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
op->dst.s_addr = htonl (OSPF_ALLSPFROUTERS);
else
- op->dst = nbr->address.u.prefix4;
+ op->dst = nbr->src;
/* Add packet to the interface output queue. */
ospf_packet_add (oi, op);
@@ -3434,7 +3445,7 @@ ospf_ls_upd_send (struct ospf_neighbor *nbr, struct list *update, int flag)
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;
+ p.prefix = nbr->src;
else if (oi->state == ISM_DR || oi->state == ISM_Backup)
p.prefix.s_addr = htonl (OSPF_ALLSPFROUTERS);
else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
@@ -3514,7 +3525,7 @@ ospf_ls_ack_send (struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
struct ospf_interface *oi = nbr->oi;
if (listcount (oi->ls_ack_direct.ls_ack) == 0)
- oi->ls_ack_direct.dst = nbr->address.u.prefix4;
+ oi->ls_ack_direct.dst = nbr->src;
listnode_add (oi->ls_ack_direct.ls_ack, ospf_lsa_lock (lsa));
@@ -3537,13 +3548,12 @@ ospf_ls_ack_send_delayed (struct ospf_interface *oi)
if (oi->type == OSPF_IFTYPE_NBMA)
{
struct ospf_neighbor *nbr;
- struct route_node *rn;
+ struct listnode *node;
- for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
- if ((nbr = rn->info) != NULL)
+ for (ALL_LIST_ELEMENTS_RO (oi->nbrs, node, nbr))
if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
while (listcount (oi->ls_ack))
- ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->address.u.prefix4);
+ ospf_ls_ack_send_list (oi, oi->ls_ack, nbr->src);
return;
}
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)