From 2cd754de60210748e61069fed2c9d4086d24c21e Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 14 Jan 2010 16:26:12 +0300 Subject: ospfd: Fix debug messages that were masked by DISCARD_LSA * ospf_packet.c: (ospf_ls_upd) DISCARD_LSA continues, and so should be after debug messages, not before them. --- ospfd/ospf_packet.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'ospfd/ospf_packet.c') diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 8f61ed1a..1066e64f 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1724,17 +1724,17 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, /* 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. */ @@ -1953,7 +1953,8 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, } } } - +#undef DISCARD_LSA + assert (listcount (lsas) == 0); list_delete (lsas); } -- cgit v1.2.3 From 0150c9c969cfbacb28fa9e05c8bf7f65448d9914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20B=C3=89RARD?= Date: Tue, 11 May 2010 10:17:53 +0200 Subject: Fix ip_len byte order in DragonFly's raw socket --- ospfd/ospf_packet.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'ospfd/ospf_packet.c') diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1066e64f..1b68fd5a 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -653,6 +653,13 @@ ospf_write (struct thread *thread) 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 @@ -2080,6 +2087,15 @@ ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) 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); -- cgit v1.2.3 From 2c9f8e36c4de4bb1412364b79c3a44881208266e Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Mon, 11 Jan 2010 16:22:12 +0000 Subject: ospfd: OSPF_MIN_LS_ARRIVAL compare should be >= to match ospf_flood * ospf_packet.c: (ospf_ls_upd) the corresponding test on the arrival side in (ospf_flood) is <, so this should be >=, not >, purely for consistency. There is no practical effect here though. --- ospfd/ospf_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ospfd/ospf_packet.c') diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1066e64f..57ed1140 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1946,7 +1946,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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); -- cgit v1.2.3 From 57c5c6526df82970ca24293798d278862cf55106 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 7 Jan 2010 06:12:53 +0000 Subject: ospfd: Reset neighbour inactivity timer for any packet arrival * The hello protocol monitors connectivity in 2 different ways: a) local -> remote b) remote -> local Connectivity is required in both directions (2-way) for adjacencies to form. The first requires a round-trip to detect, and is done by advertising which other hosts a router knows about in its hello messages. This allows a host to detect which other routers are and are not receiving its message. If a remote neighbour delists the local router, then the local router raises a "1-Way Received" event. The latter is straight-forward, and is detected by setting a timer for the neighbour. If another Hello packet is not received within this time then the neighbour is dead, and a separate "Inactive" event is raised. These are 2 different and relatively independent measures. Knowing that we can optimise the 2nd, remote->local measure and reset the timer when /any/ packet arrives from that neighbour. For any packet is as good as a Hello packet. This can help in marginal situations, where the number of protocol messages that must be sent sometimes can exceed the capacity of the network to transmit the messages within the configured dead-time. I.e. an OSPF network with lots of LSAs, slow links and/or slow hosts (e.g. O(10k) LSAs, O(100kbit) links, embedded CPUs, and O(10s) dead-times). This optimisation allows an OSPF network to run closer to this margin, and/or allows networks to perhaps better cope with rare periods of exceptional load, where otherwise they would not. It's fully compatible with plain OSPF implementations and doesn't prejudice dead-neighbour detection. * ospf_nsm.h: Rename HelloReceived event to PacketReceived. * ospf_nsm.c: (nsm_hello_received) -> nsm_packet_received * ospf_packet.c: Schedule PacketReceived whenever a valid message is received. --- ospfd/ospf_packet.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'ospfd/ospf_packet.c') diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 57ed1140..80641b49 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -881,7 +881,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,7 +901,7 @@ 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); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_OneWayReceived); nbr->priority = hello->priority; nbr->d_router = hello->d_router; nbr->bd_router = hello->bd_router; @@ -911,12 +911,12 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, 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; @@ -1191,6 +1191,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) { @@ -1412,6 +1415,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 +1650,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 +1986,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: " -- cgit v1.2.3 From aa276fd783f5cdbeefe22bf54109fe523a465e07 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Fri, 8 Jan 2010 17:11:15 +0000 Subject: ospfd: Prioritise hellos for sending by queueing to head of output buffer * It's possible for the packet output buffer to be filled up with a long series of non-Hello packets in between Hellos packets, such that the router's neighbours don't receive the Hello packet in time, even though the hello-timer ran at about the right time. Fix this by prioritising Hello packets, letting them skip the queue and go ahead of any packets already on the queue. This problem can occur when there are lots of LSAs and slow links. * ospf_packet.h: (ospf_hello_send_sub) not used outside of ospf_packet.c * ospf_packet.c: (ospf_fifo_push_head) add packet to head of fifo (so its no longer really a fifo, but hey) (ospf_packet_add_top) add packet to top of the packet output queue. (ospf_hello_send_sub) Put Hello's at the top of the packet output queue. make it take in_addr_t parameter, so that this ospf_hello_send can re-use this code too. (ospf_hello_send) consolidate code by using ospf_hello_send_sub (ospf_poll_send,ospf_hello_reply_timer) adjust for ospf_hello_send_sub. --- ospfd/ospf_packet.c | 94 +++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 46 deletions(-) (limited to 'ospfd/ospf_packet.c') diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 80641b49..8b7c63a9 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) { @@ -2967,8 +3002,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; @@ -2987,10 +3022,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); @@ -3021,7 +3058,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 @@ -3060,7 +3097,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->address.u.prefix4.s_addr); return 0; } @@ -3069,27 +3106,10 @@ 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; @@ -3119,34 +3139,16 @@ ospf_hello_send (struct ospf_interface *oi) 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)); } } -- cgit v1.2.3