void ospf_lsack_send(struct ospf_neighbor *n, int queue) { struct ospf_packet *op; struct ospf_lsack_packet *pk; u16 len, i = 0; struct ospf_lsa_header *h; struct lsah_n *no; struct ospf_iface *ifa = n->ifa; struct proto *p = &n->ifa->oa->po->proto; if (EMPTY_LIST(n->ackl[queue])) return; pk = (struct ospf_lsack_packet *) ifa->sk->tbuf; op = (struct ospf_packet *) ifa->sk->tbuf; ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P); h = pk->lsh; while (!EMPTY_LIST(n->ackl[queue])) { no = (struct lsah_n *) HEAD(n->ackl[queue]); memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header)); DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id), ntohl((h + i)->rt), (h + i)->type); i++; rem_node(NODE no); mb_free(no); if ((i * sizeof(struct ospf_lsa_header) + sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa)) { if (!EMPTY_LIST(n->ackl[queue])) { len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header); op->length = htons(len); DBG("Sending and continuing! Len=%u\n", len); OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf, "LSACK packet sent via %s", ifa->iface->name); if (ifa->type == OSPF_IT_BCAST) { if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) ospf_send_to(ifa, AllSPFRouters); else ospf_send_to(ifa, AllDRouters); } else { if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); else ospf_send_to_bdr(ifa); } ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P); i = 0; } } } len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header); op->length = htons(len); DBG("Sending! Len=%u\n", len); OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf, "LSACK packet sent via %s", ifa->iface->name); if (ifa->type == OSPF_IT_BCAST) { if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) ospf_send_to(ifa, AllSPFRouters); else ospf_send_to(ifa, AllDRouters); } else ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); }
/** * ospf_dbdes_send - transmit database description packet * @n: neighbor * @next: whether to send a next packet in a sequence (1) or to retransmit the old one (0) * * Sending of a database description packet is described in 10.8 of RFC 2328. * Reception of each packet is acknowledged in the sequence number of another. * When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor * does not reply, I don't create a new packet but just send the content * of the buffer. */ void ospf_dbdes_send(struct ospf_neighbor *n, int next) { struct ospf_dbdes_packet *pkt; struct ospf_packet *op; struct ospf_iface *ifa = n->ifa; struct ospf_area *oa = ifa->oa; struct proto_ospf *po = oa->po; struct proto *p = &po->proto; u16 length, i, j; /* FIXME ??? */ if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal))) update_rt_lsa(oa); switch (n->state) { case NEIGHBOR_EXSTART: /* Send empty packets */ n->myimms.bit.i = 1; pkt = ospf_tx_buffer(ifa); op = &pkt->ospf_packet; ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); pkt->iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : htons(ifa->iface->mtu); pkt->options = hton_opt(oa->options); pkt->imms = n->myimms; pkt->ddseq = htonl(n->dds); length = sizeof(struct ospf_dbdes_packet); op->length = htons(length); OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name); ospf_send_to(ifa, n->ip); break; case NEIGHBOR_EXCHANGE: n->myimms.bit.i = 0; if (next) { snode *sn; struct ospf_lsa_header *lsa; pkt = n->ldbdes; op = (struct ospf_packet *) pkt; ospf_pkt_fill_hdr(ifa, pkt, DBDES_P); pkt->iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : htons(ifa->iface->mtu); pkt->ddseq = htonl(n->dds); pkt->options = hton_opt(oa->options); j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */ lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet)); if (n->myimms.bit.m) { sn = s_get(&(n->dbsi)); DBG("Number of LSA: %d\n", j); for (; i > 0; i--) { struct top_hash_entry *en= (struct top_hash_entry *) sn; if (ospf_lsa_flooding_allowed(&en->lsa, en->domain, ifa)) { htonlsah(&(en->lsa), lsa); DBG("Working on: %d\n", i); DBG("\tX%01x %-1R %-1R %p\n", en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa_body); lsa++; } else i++; /* No lsa added */ if (sn == STAIL(po->lsal)) { i--; break; } sn = sn->next; } if (sn == STAIL(po->lsal)) { DBG("Number of LSA NOT sent: %d\n", i); DBG("M bit unset.\n"); n->myimms.bit.m = 0; /* Unset more bit */ } s_put(&(n->dbsi), sn); } pkt->imms.byte = n->myimms.byte; length = (j - i) * sizeof(struct ospf_lsa_header) + sizeof(struct ospf_dbdes_packet); op->length = htons(length); DBG("%s: DB_DES (M) prepared for %I.\n", p->name, n->ip); } case NEIGHBOR_LOADING: case NEIGHBOR_FULL: length = ntohs(((struct ospf_packet *) n->ldbdes)->length); if (!length) { OSPF_TRACE(D_PACKETS, "No packet in my buffer for repeating"); ospf_neigh_sm(n, INM_KILLNBR); return; } /* Copy last sent packet again */ pkt = ospf_tx_buffer(ifa); memcpy(pkt, n->ldbdes, length); OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name); ospf_send_to(ifa, n->ip); if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */ if (!n->myimms.bit.ms) { if ((n->myimms.bit.m == 0) && (n->imms.bit.m == 0) && (n->state == NEIGHBOR_EXCHANGE)) { ospf_neigh_sm(n, INM_EXDONE); } } break; default: /* Ignore it */ break; } }