--- embedaddon/quagga/ospf6d/ospf6_message.c 2012/02/21 17:26:12 1.1 +++ embedaddon/quagga/ospf6d/ospf6_message.c 2016/11/02 10:09:12 1.1.1.4 @@ -47,9 +47,18 @@ #include "ospf6_flood.h" #include "ospf6d.h" +#include + unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0}; -const char *ospf6_message_type_str[] = - { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" }; +static const struct message ospf6_message_type_str [] = +{ + { OSPF6_MESSAGE_TYPE_HELLO, "Hello" }, + { OSPF6_MESSAGE_TYPE_DBDESC, "DbDesc" }, + { OSPF6_MESSAGE_TYPE_LSREQ, "LSReq" }, + { OSPF6_MESSAGE_TYPE_LSUPDATE, "LSUpdate" }, + { OSPF6_MESSAGE_TYPE_LSACK, "LSAck" }, +}; +static const size_t ospf6_message_type_str_max = array_size(ospf6_message_type_str); /* Minimum (besides the standard OSPF packet header) lengths for OSPF packets of particular types, offset is the "type" field. */ @@ -126,8 +135,7 @@ ospf6_hello_print (struct ospf6_header *oh) zlog_debug (" Neighbor: %s", neighbor); } - if (p != OSPF6_MESSAGE_END (oh)) - zlog_debug ("Trailing garbage exists"); + assert (p == OSPF6_MESSAGE_END (oh)); } void @@ -159,8 +167,7 @@ ospf6_dbdesc_print (struct ospf6_header *oh) p += sizeof (struct ospf6_lsa_header)) ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p); - if (p != OSPF6_MESSAGE_END (oh)) - zlog_debug ("Trailing garbage exists"); + assert (p == OSPF6_MESSAGE_END (oh)); } void @@ -183,8 +190,7 @@ ospf6_lsreq_print (struct ospf6_header *oh) ospf6_lstype_name (e->type), id, adv_router); } - if (p != OSPF6_MESSAGE_END (oh)) - zlog_debug ("Trailing garbage exists"); + assert (p == OSPF6_MESSAGE_END (oh)); } void @@ -209,35 +215,9 @@ ospf6_lsupdate_print (struct ospf6_header *oh) p += OSPF6_LSA_SIZE (p)) { ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p); - if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header)) - { - zlog_debug (" Malformed LSA length, quit printing"); - break; - } } - if (p != OSPF6_MESSAGE_END (oh)) - { - char buf[32]; - - int num = 0; - memset (buf, 0, sizeof (buf)); - - zlog_debug (" Trailing garbage exists"); - while (p < OSPF6_MESSAGE_END (oh)) - { - snprintf (buf, sizeof (buf), "%s %2x", buf, *p++); - num++; - if (num == 8) - { - zlog_debug (" %s", buf); - memset (buf, 0, sizeof (buf)); - num = 0; - } - } - if (num) - zlog_debug (" %s", buf); - } + assert (p == OSPF6_MESSAGE_END (oh)); } void @@ -253,8 +233,7 @@ ospf6_lsack_print (struct ospf6_header *oh) p += sizeof (struct ospf6_lsa_header)) ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p); - if (p != OSPF6_MESSAGE_END (oh)) - zlog_debug ("Trailing garbage exists"); + assert (p == OSPF6_MESSAGE_END (oh)); } static void @@ -321,11 +300,7 @@ ospf6_hello_recv (struct in6_addr *src, struct in6_add twoway++; } - if (p != OSPF6_MESSAGE_END (oh)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Trailing garbage ignored"); - } + assert (p == OSPF6_MESSAGE_END (oh)); /* RouterPriority check */ if (on->priority != hello->priority) @@ -542,33 +517,29 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh, { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Add request (No database copy)"); - ospf6_lsdb_add (his, on->request_list); + ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list); } else if (ospf6_lsa_compare (his, mine) < 0) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Add request (Received MoreRecent)"); - ospf6_lsdb_add (his, on->request_list); + ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list); } else { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Discard (Existing MoreRecent)"); - ospf6_lsa_delete (his); } + ospf6_lsa_delete (his); } - if (p != OSPF6_MESSAGE_END (oh)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Trailing garbage ignored"); - } + assert (p == OSPF6_MESSAGE_END (oh)); /* Increment sequence number */ on->dbdesc_seqnum ++; /* schedule send lsreq */ - if (on->thread_send_lsreq == NULL) + if (on->request_list->count && (on->thread_send_lsreq == NULL)) on->thread_send_lsreq = thread_add_event (master, ospf6_lsreq_send, on, 0); @@ -764,23 +735,19 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh, { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Add request-list: %s", his->name); - ospf6_lsdb_add (his, on->request_list); + ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list); } - else - ospf6_lsa_delete (his); + ospf6_lsa_delete (his); } - if (p != OSPF6_MESSAGE_END (oh)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Trailing garbage ignored"); - } + assert (p == OSPF6_MESSAGE_END (oh)); /* Set sequence number to Master's */ on->dbdesc_seqnum = ntohl (dbdesc->seqnum); /* schedule send lsreq */ - if (on->thread_send_lsreq == NULL) + if ((on->thread_send_lsreq == NULL) && + (on->request_list->count)) on->thread_send_lsreq = thread_add_event (master, ospf6_lsreq_send, on, 0); @@ -910,11 +877,7 @@ ospf6_lsreq_recv (struct in6_addr *src, struct in6_add ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list); } - if (p != OSPF6_MESSAGE_END (oh)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Trailing garbage ignored"); - } + assert (p == OSPF6_MESSAGE_END (oh)); /* schedule send lsupdate */ THREAD_OFF (on->thread_send_lsupdate); @@ -1140,7 +1103,7 @@ ospf6_lsaseq_examin if (length < OSPF6_LSA_HEADER_SIZE) { if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: undersized (%u B) trailing (#%u) LSA header", + zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header", __func__, length, counted_lsas); return MSG_NG; } @@ -1172,7 +1135,7 @@ ospf6_lsaseq_examin if (lsalen > length) { if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %u B", + zlog_debug ("%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B", __func__, ospf6_lstype_name (lsah->type), counted_lsas, lsalen, length); return MSG_NG; } @@ -1238,7 +1201,7 @@ ospf6_packet_examin (struct ospf6_header *oh, const un { if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) zlog_debug ("%s: undersized (%u B) %s packet", __func__, - bytesonwire, ospf6_message_type_str[oh->type]); + bytesonwire, LOOKUP (ospf6_message_type_str, oh->type)); return MSG_NG; } /* type-specific deeper validation */ @@ -1251,7 +1214,7 @@ ospf6_packet_examin (struct ospf6_header *oh, const un return MSG_OK; if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) zlog_debug ("%s: alignment error in %s packet", - __func__, ospf6_message_type_str[oh->type]); + __func__, LOOKUP (ospf6_message_type_str, oh->type)); return MSG_NG; case OSPF6_MESSAGE_TYPE_DBDESC: /* RFC5340 A.3.3, packet header + OSPF6_DB_DESC_MIN_SIZE bytes followed @@ -1270,7 +1233,7 @@ ospf6_packet_examin (struct ospf6_header *oh, const un return MSG_OK; if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) zlog_debug ("%s: alignment error in %s packet", - __func__, ospf6_message_type_str[oh->type]); + __func__, LOOKUP (ospf6_message_type_str, oh->type)); return MSG_NG; case OSPF6_MESSAGE_TYPE_LSUPDATE: /* RFC5340 A.3.5, packet header + OSPF6_LS_UPD_MIN_SIZE bytes followed @@ -1300,7 +1263,7 @@ ospf6_packet_examin (struct ospf6_header *oh, const un return MSG_NG; } if (test != MSG_OK && IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("%s: anomaly in %s packet", __func__, ospf6_message_type_str[oh->type]); + zlog_debug ("%s: anomaly in %s packet", __func__, LOOKUP (ospf6_message_type_str, oh->type)); return test; } @@ -1319,7 +1282,7 @@ ospf6_rxpacket_examin (struct ospf6_interface *oi, str { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) { - if (oh->area_id == BACKBONE_AREA_ID) + if (oh->area_id == OSPF_AREA_BACKBONE) zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__); else zlog_debug @@ -1355,7 +1318,6 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_ { struct ospf6_neighbor *on; struct ospf6_lsupdate *lsupdate; - unsigned long num; char *p; on = ospf6_neighbor_lookup (oh->router_id, oi); @@ -1378,51 +1340,17 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_ lsupdate = (struct ospf6_lsupdate *) ((caddr_t) oh + sizeof (struct ospf6_header)); - num = ntohl (lsupdate->lsa_number); - /* Process LSAs */ for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); p < OSPF6_MESSAGE_END (oh) && p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh); p += OSPF6_LSA_SIZE (p)) { - if (num == 0) - break; - if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Malformed LSA length, quit processing"); - break; - } - ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p); - num--; } - if (num != 0) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Malformed LSA number or LSA length"); - } - if (p != OSPF6_MESSAGE_END (oh)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Trailing garbage ignored"); - } + assert (p == OSPF6_MESSAGE_END (oh)); - /* RFC2328 Section 10.9: When the neighbor responds to these requests - with the proper Link State Update packet(s), the Link state request - list is truncated and a new Link State Request packet is sent. */ - /* send new Link State Request packet if this LS Update packet - can be recognized as a response to our previous LS Request */ - if (! IN6_IS_ADDR_MULTICAST (dst) && - (on->state == OSPF6_NEIGHBOR_EXCHANGE || - on->state == OSPF6_NEIGHBOR_LOADING)) - { - THREAD_OFF (on->thread_send_lsreq); - on->thread_send_lsreq = - thread_add_event (master, ospf6_lsreq_send, on, 0); - } } static void @@ -1524,11 +1452,7 @@ ospf6_lsack_recv (struct in6_addr *src, struct in6_add ospf6_lsa_delete (his); } - if (p != OSPF6_MESSAGE_END (oh)) - { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Trailing garbage ignored"); - } + assert (p == OSPF6_MESSAGE_END (oh)); } static u_char *recvbuf = NULL; @@ -1591,7 +1515,7 @@ ospf6_receive (struct thread *thread) unsigned int len; char srcname[64], dstname[64]; struct in6_addr src, dst; - unsigned int ifindex; + ifindex_t ifindex; struct iovec iovector[2]; struct ospf6_interface *oi; struct ospf6_header *oh; @@ -1619,7 +1543,7 @@ ospf6_receive (struct thread *thread) } oi = ospf6_interface_lookup_by_ifindex (ifindex); - if (oi == NULL || oi->area == NULL) + if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) { zlog_debug ("Message received on disabled interface"); return 0; @@ -1647,11 +1571,9 @@ ospf6_receive (struct thread *thread) inet_ntop (AF_INET6, &src, srcname, sizeof (srcname)); inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname)); zlog_debug ("%s received on %s", - OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name); + LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name); zlog_debug (" src: %s", srcname); zlog_debug (" dst: %s", dstname); - if (len != ntohs (oh->length)) - zlog_debug ("Message length does not match actually received: %d", len); switch (oh->type) { @@ -1671,8 +1593,7 @@ ospf6_receive (struct thread *thread) ospf6_lsack_print (oh); break; default: - zlog_debug ("Unknown message"); - break; + assert (0); } } @@ -1699,9 +1620,7 @@ ospf6_receive (struct thread *thread) break; default: - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV)) - zlog_debug ("Unknown message"); - break; + assert (0); } return 0; @@ -1711,7 +1630,7 @@ static void ospf6_send (struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *oi, struct ospf6_header *oh) { - int len; + unsigned int len; char srcname[64], dstname[64]; struct iovec iovector[2]; @@ -1740,7 +1659,7 @@ ospf6_send (struct in6_addr *src, struct in6_addr *dst else memset (srcname, 0, sizeof (srcname)); zlog_debug ("%s send on %s", - OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name); + LOOKUP (ospf6_message_type_str, oh->type), oi->interface->name); zlog_debug (" src: %s", srcname); zlog_debug (" dst: %s", dstname); @@ -1774,6 +1693,13 @@ ospf6_send (struct in6_addr *src, struct in6_addr *dst zlog_err ("Could not send entire message"); } +static uint32_t +ospf6_packet_max(struct ospf6_interface *oi) +{ + assert (oi->ifmtu > sizeof (struct ip6_hdr)); + return oi->ifmtu - (sizeof (struct ip6_hdr)); +} + int ospf6_hello_send (struct thread *thread) { @@ -1795,6 +1721,13 @@ ospf6_hello_send (struct thread *thread) return 0; } + if (iobuflen == 0) + { + zlog_debug ("Unable to send Hello on interface %s iobuflen is 0", + oi->interface->name); + return 0; + } + /* set next thread */ oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, oi, oi->hello_interval); @@ -1820,7 +1753,7 @@ ospf6_hello_send (struct thread *thread) if (on->state < OSPF6_NEIGHBOR_INIT) continue; - if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu) + if (p - sendbuf + sizeof (u_int32_t) > ospf6_packet_max(oi)) { if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND)) zlog_debug ("sending Hello message: exceeds I/F MTU"); @@ -1846,6 +1779,7 @@ ospf6_dbdesc_send (struct thread *thread) struct ospf6_dbdesc *dbdesc; u_char *p; struct ospf6_lsa *lsa; + struct in6_addr *dst; on = (struct ospf6_neighbor *) THREAD_ARG (thread); on->thread_send_dbdesc = (struct thread *) NULL; @@ -1870,7 +1804,8 @@ ospf6_dbdesc_send (struct thread *thread) sizeof (struct ospf6_header)); /* if this is initial one, initialize sequence number for DbDesc */ - if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT)) + if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) && + (on->dbdesc_seqnum == 0)) { struct timeval tv; if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0) @@ -1896,9 +1831,9 @@ ospf6_dbdesc_send (struct thread *thread) /* MTU check */ if (p - sendbuf + sizeof (struct ospf6_lsa_header) > - on->ospf6_if->ifmtu) + ospf6_packet_max(on->ospf6_if)) { - ospf6_lsa_unlock (lsa); + ospf6_lsdb_lsa_unlock (lsa); break; } memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); @@ -1909,8 +1844,14 @@ ospf6_dbdesc_send (struct thread *thread) oh->type = OSPF6_MESSAGE_TYPE_DBDESC; oh->length = htons (p - sendbuf); - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); + + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + dst = &allspfrouters6; + else + dst = &on->linklocal_addr; + + ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh); + return 0; } @@ -1930,9 +1871,9 @@ ospf6_dbdesc_send_newone (struct thread *thread) for (lsa = ospf6_lsdb_head (on->summary_list); lsa; lsa = ospf6_lsdb_next (lsa)) { - if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu) + if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if)) { - ospf6_lsa_unlock (lsa); + ospf6_lsdb_lsa_unlock (lsa); break; } @@ -1961,7 +1902,7 @@ ospf6_lsreq_send (struct thread *thread) struct ospf6_header *oh; struct ospf6_lsreq_entry *e; u_char *p; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *last_req; on = (struct ospf6_neighbor *) THREAD_ARG (thread); on->thread_send_lsreq = (struct thread *) NULL; @@ -1983,13 +1924,9 @@ ospf6_lsreq_send (struct thread *thread) return 0; } - /* set next thread */ - on->thread_send_lsreq = - thread_add_timer (master, ospf6_lsreq_send, on, - on->ospf6_if->rxmt_interval); - memset (sendbuf, 0, iobuflen); oh = (struct ospf6_header *) sendbuf; + last_req = NULL; /* set Request entries in lsreq */ p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); @@ -1997,9 +1934,9 @@ ospf6_lsreq_send (struct thread *thread) lsa = ospf6_lsdb_next (lsa)) { /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu) + if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if)) { - ospf6_lsa_unlock (lsa); + ospf6_lsdb_lsa_unlock (lsa); break; } @@ -2008,13 +1945,37 @@ ospf6_lsreq_send (struct thread *thread) e->id = lsa->header->id; e->adv_router = lsa->header->adv_router; p += sizeof (struct ospf6_lsreq_entry); + last_req = lsa; } + if (last_req != NULL) + { + if (on->last_ls_req != NULL) + { + ospf6_lsa_unlock (on->last_ls_req); + } + ospf6_lsa_lock (last_req); + on->last_ls_req = last_req; + } + oh->type = OSPF6_MESSAGE_TYPE_LSREQ; oh->length = htons (p - sendbuf); - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6, on->ospf6_if, oh); + else + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); + + /* set next thread */ + if (on->request_list->count != 0) + { + on->thread_send_lsreq = + thread_add_timer (master, ospf6_lsreq_send, on, + on->ospf6_if->rxmt_interval); + } + return 0; } @@ -2025,7 +1986,7 @@ ospf6_lsupdate_send_neighbor (struct thread *thread) struct ospf6_header *oh; struct ospf6_lsupdate *lsupdate; u_char *p; - int num; + int lsa_cnt; struct ospf6_lsa *lsa; on = (struct ospf6_neighbor *) THREAD_ARG (thread); @@ -2042,22 +2003,13 @@ ospf6_lsupdate_send_neighbor (struct thread *thread) return 0; } - /* if we have nothing to send, return */ - if (on->lsupdate_list->count == 0 && - on->retrans_list->count == 0) - { - if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) - zlog_debug ("Quit to send (nothing to send)"); - return 0; - } - memset (sendbuf, 0, iobuflen); oh = (struct ospf6_header *) sendbuf; lsupdate = (struct ospf6_lsupdate *) ((caddr_t) oh + sizeof (struct ospf6_header)); p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - num = 0; + lsa_cnt = 0; /* lsupdate_list lists those LSA which doesn't need to be retransmitted. remove those from the list */ @@ -2066,58 +2018,85 @@ ospf6_lsupdate_send_neighbor (struct thread *thread) { /* MTU check */ if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header)) - > on->ospf6_if->ifmtu) - { - ospf6_lsa_unlock (lsa); - break; - } + > ospf6_packet_max(on->ospf6_if)) + { + ospf6_lsdb_lsa_unlock (lsa); + break; + } ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); p += OSPF6_LSA_SIZE (lsa->header); - num++; + lsa_cnt++; assert (lsa->lock == 2); ospf6_lsdb_remove (lsa, on->lsupdate_list); } + if (lsa_cnt) + { + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons (p - sendbuf); + lsupdate->lsa_number = htonl (lsa_cnt); + + if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) || + (on->ospf6_if->state == OSPF6_INTERFACE_DR) || + (on->ospf6_if->state == OSPF6_INTERFACE_BDR)) + ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6, + on->ospf6_if, oh); + else + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); + } + + /* The addresses used for retransmissions are different from those sent the + first time and so we need to separate them here. + */ + memset (sendbuf, 0, iobuflen); + oh = (struct ospf6_header *) sendbuf; + lsupdate = (struct ospf6_lsupdate *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + lsa_cnt = 0; + for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; lsa = ospf6_lsdb_next (lsa)) { /* MTU check */ if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header)) - > on->ospf6_if->ifmtu) - { - ospf6_lsa_unlock (lsa); - break; - } + > ospf6_packet_max(on->ospf6_if)) + { + ospf6_lsdb_lsa_unlock (lsa); + break; + } ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); p += OSPF6_LSA_SIZE (lsa->header); - num++; + lsa_cnt++; } - lsupdate->lsa_number = htonl (num); - - oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; - oh->length = htons (p - sendbuf); - - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); - - if (on->lsupdate_list->count != 0 || - on->retrans_list->count != 0) + if (lsa_cnt) { - if (on->lsupdate_list->count != 0) - on->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons (p - sendbuf); + lsupdate->lsa_number = htonl (lsa_cnt); + + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) + ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6, + on->ospf6_if, oh); else - on->thread_send_lsupdate = - thread_add_timer (master, ospf6_lsupdate_send_neighbor, on, - on->ospf6_if->rxmt_interval); + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); } + if (on->lsupdate_list->count != 0) + on->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); + else if (on->retrans_list->count != 0) + on->thread_send_lsupdate = + thread_add_timer (master, ospf6_lsupdate_send_neighbor, on, + on->ospf6_if->rxmt_interval); return 0; } @@ -2128,7 +2107,7 @@ ospf6_lsupdate_send_interface (struct thread *thread) struct ospf6_header *oh; struct ospf6_lsupdate *lsupdate; u_char *p; - int num; + int lsa_cnt; struct ospf6_lsa *lsa; oi = (struct ospf6_interface *) THREAD_ARG (thread); @@ -2149,42 +2128,47 @@ ospf6_lsupdate_send_interface (struct thread *thread) memset (sendbuf, 0, iobuflen); oh = (struct ospf6_header *) sendbuf; lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh + - sizeof (struct ospf6_header)); + sizeof (struct ospf6_header)); p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); - num = 0; + lsa_cnt = 0; for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa; lsa = ospf6_lsdb_next (lsa)) { /* MTU check */ if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header))) - > oi->ifmtu) - { - ospf6_lsa_unlock (lsa); - break; - } + > ospf6_packet_max(oi)) + { + ospf6_lsdb_lsa_unlock (lsa); + break; + } ospf6_lsa_age_update_to_send (lsa, oi->transdelay); memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); p += OSPF6_LSA_SIZE (lsa->header); - num++; + lsa_cnt++; assert (lsa->lock == 2); ospf6_lsdb_remove (lsa, oi->lsupdate_list); } - lsupdate->lsa_number = htonl (num); + if (lsa_cnt) + { + lsupdate->lsa_number = htonl (lsa_cnt); - oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; - oh->length = htons (p - sendbuf); + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons (p - sendbuf); - if (oi->state == OSPF6_INTERFACE_DR || - oi->state == OSPF6_INTERFACE_BDR) - ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); - else - ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); + if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) || + (oi->state == OSPF6_INTERFACE_DR) || + (oi->state == OSPF6_INTERFACE_BDR)) + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); + else + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); + } + if (oi->lsupdate_list->count > 0) { oi->thread_send_lsupdate = @@ -2201,6 +2185,7 @@ ospf6_lsack_send_neighbor (struct thread *thread) struct ospf6_header *oh; u_char *p; struct ospf6_lsa *lsa; + int lsa_cnt = 0; on = (struct ospf6_neighbor *) THREAD_ARG (thread); on->thread_send_lsack = (struct thread *) NULL; @@ -2226,17 +2211,17 @@ ospf6_lsack_send_neighbor (struct thread *thread) lsa = ospf6_lsdb_next (lsa)) { /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu) - { - /* if we run out of packet size/space here, - better to try again soon. */ - THREAD_OFF (on->thread_send_lsack); - on->thread_send_lsack = - thread_add_event (master, ospf6_lsack_send_neighbor, on, 0); + if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if)) + { + /* if we run out of packet size/space here, + better to try again soon. */ + THREAD_OFF (on->thread_send_lsack); + on->thread_send_lsack = + thread_add_event (master, ospf6_lsack_send_neighbor, on, 0); - ospf6_lsa_unlock (lsa); - break; - } + ospf6_lsdb_lsa_unlock (lsa); + break; + } ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); @@ -2244,13 +2229,24 @@ ospf6_lsack_send_neighbor (struct thread *thread) assert (lsa->lock == 2); ospf6_lsdb_remove (lsa, on->lsack_list); + lsa_cnt++; } - oh->type = OSPF6_MESSAGE_TYPE_LSACK; - oh->length = htons (p - sendbuf); + if (lsa_cnt) + { + oh->type = OSPF6_MESSAGE_TYPE_LSACK; + oh->length = htons (p - sendbuf); - ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, - on->ospf6_if, oh); + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); + } + + if (on->thread_send_lsack == NULL && on->lsack_list->count > 0) + { + on->thread_send_lsack = + thread_add_event (master, ospf6_lsack_send_neighbor, on, 0); + } + return 0; } @@ -2261,6 +2257,7 @@ ospf6_lsack_send_interface (struct thread *thread) struct ospf6_header *oh; u_char *p; struct ospf6_lsa *lsa; + int lsa_cnt = 0; oi = (struct ospf6_interface *) THREAD_ARG (thread); oi->thread_send_lsack = (struct thread *) NULL; @@ -2286,17 +2283,17 @@ ospf6_lsack_send_interface (struct thread *thread) lsa = ospf6_lsdb_next (lsa)) { /* MTU check */ - if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu) - { - /* if we run out of packet size/space here, - better to try again soon. */ - THREAD_OFF (oi->thread_send_lsack); - oi->thread_send_lsack = - thread_add_event (master, ospf6_lsack_send_interface, oi, 0); + if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi)) + { + /* if we run out of packet size/space here, + better to try again soon. */ + THREAD_OFF (oi->thread_send_lsack); + oi->thread_send_lsack = + thread_add_event (master, ospf6_lsack_send_interface, oi, 0); - ospf6_lsa_unlock (lsa); - break; - } + ospf6_lsdb_lsa_unlock (lsa); + break; + } ospf6_lsa_age_update_to_send (lsa, oi->transdelay); memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); @@ -2304,16 +2301,21 @@ ospf6_lsack_send_interface (struct thread *thread) assert (lsa->lock == 2); ospf6_lsdb_remove (lsa, oi->lsack_list); + lsa_cnt++; } - oh->type = OSPF6_MESSAGE_TYPE_LSACK; - oh->length = htons (p - sendbuf); + if (lsa_cnt) + { + oh->type = OSPF6_MESSAGE_TYPE_LSACK; + oh->length = htons (p - sendbuf); - if (oi->state == OSPF6_INTERFACE_DR || - oi->state == OSPF6_INTERFACE_BDR) - ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); - else - ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); + if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) || + (oi->state == OSPF6_INTERFACE_DR) || + (oi->state == OSPF6_INTERFACE_BDR)) + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); + else + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); + } if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0) { @@ -2324,7 +2326,7 @@ ospf6_lsack_send_interface (struct thread *thread) return 0; } - + /* Commands */ DEFUN (debug_ospf6_message, debug_ospf6_message_cmd, @@ -2398,7 +2400,7 @@ ALIAS (debug_ospf6_message, "Debug only receiving message\n" ) - + DEFUN (no_debug_ospf6_message, no_debug_ospf6_message_cmd, "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",