Annotation of embedaddon/bird/proto/ospf/lsack.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD -- OSPF
! 3: *
! 4: * (c) 2000--2004 Ondrej Filip <feela@network.cz>
! 5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
! 6: * (c) 2009--2014 CZ.NIC z.s.p.o.
! 7: *
! 8: * Can be freely distributed and used under the terms of the GNU GPL.
! 9: */
! 10:
! 11: #include "ospf.h"
! 12:
! 13:
! 14: /*
! 15: struct ospf_lsack_packet
! 16: {
! 17: struct ospf_packet hdr;
! 18: // union ospf_auth auth;
! 19:
! 20: struct ospf_lsa_header lsas[];
! 21: };
! 22: */
! 23:
! 24: struct lsa_node
! 25: {
! 26: node n;
! 27: struct ospf_lsa_header lsa;
! 28: };
! 29:
! 30:
! 31: static inline void
! 32: ospf_lsack_body(struct ospf_proto *p, struct ospf_packet *pkt,
! 33: struct ospf_lsa_header **body, uint *count)
! 34: {
! 35: uint plen = ntohs(pkt->length);
! 36: uint hlen = ospf_pkt_hdrlen(p);
! 37:
! 38: *body = ((void *) pkt) + hlen;
! 39: *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
! 40: }
! 41:
! 42: static void
! 43: ospf_dump_lsack(struct ospf_proto *p, struct ospf_packet *pkt)
! 44: {
! 45: struct ospf_lsa_header *lsas;
! 46: uint i, lsa_count;
! 47:
! 48: ASSERT(pkt->type == LSACK_P);
! 49: ospf_dump_common(p, pkt);
! 50:
! 51: ospf_lsack_body(p, pkt, &lsas, &lsa_count);
! 52: for (i = 0; i < lsa_count; i++)
! 53: ospf_dump_lsahdr(p, lsas + i);
! 54: }
! 55:
! 56:
! 57: void
! 58: ospf_enqueue_lsack(struct ospf_neighbor *n, struct ospf_lsa_header *h_n, int queue)
! 59: {
! 60: /* Note that h_n is in network endianity */
! 61: struct lsa_node *no = mb_alloc(n->pool, sizeof(struct lsa_node));
! 62: memcpy(&no->lsa, h_n, sizeof(struct ospf_lsa_header));
! 63: add_tail(&n->ackl[queue], NODE no);
! 64: DBG("Adding %s ack for %R, ID: %R, RT: %R, Type: %u\n",
! 65: (queue == ACKL_DIRECT) ? "direct" : "delayed",
! 66: n->rid, ntohl(h_n->id), ntohl(h_n->rt), h_n->type);
! 67: }
! 68:
! 69: void
! 70: ospf_reset_lsack_queue(struct ospf_neighbor *n)
! 71: {
! 72: struct lsa_node *no;
! 73:
! 74: WALK_LIST_FIRST(no, n->ackl[ACKL_DELAY])
! 75: {
! 76: rem_node(NODE no);
! 77: mb_free(no);
! 78: }
! 79: }
! 80:
! 81: static inline void
! 82: ospf_send_lsack_(struct ospf_proto *p, struct ospf_neighbor *n, int queue)
! 83: {
! 84: struct ospf_iface *ifa = n->ifa;
! 85: struct ospf_lsa_header *lsas;
! 86: struct ospf_packet *pkt;
! 87: struct lsa_node *no;
! 88: uint i, lsa_max, length;
! 89:
! 90: /* RFC 2328 13.5 */
! 91:
! 92: pkt = ospf_tx_buffer(ifa);
! 93: ospf_pkt_fill_hdr(ifa, pkt, LSACK_P);
! 94: ospf_lsack_body(p, pkt, &lsas, &lsa_max);
! 95:
! 96: for (i = 0; i < lsa_max && !EMPTY_LIST(n->ackl[queue]); i++)
! 97: {
! 98: no = (struct lsa_node *) HEAD(n->ackl[queue]);
! 99: memcpy(&lsas[i], &no->lsa, sizeof(struct ospf_lsa_header));
! 100: DBG("Iter %u ID: %R, RT: %R, Type: %04x\n",
! 101: i, ntohl(lsas[i].id), ntohl(lsas[i].rt), lsas[i].type);
! 102: rem_node(NODE no);
! 103: mb_free(no);
! 104: }
! 105:
! 106: length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsa_header);
! 107: pkt->length = htons(length);
! 108:
! 109: OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet sent via %s", ifa->ifname);
! 110:
! 111: if (ifa->type == OSPF_IT_BCAST)
! 112: {
! 113: if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
! 114: ospf_send_to_all(ifa);
! 115: else
! 116: ospf_send_to_des(ifa);
! 117: }
! 118: else
! 119: ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
! 120: }
! 121:
! 122: void
! 123: ospf_send_lsack(struct ospf_proto *p, struct ospf_neighbor *n, int queue)
! 124: {
! 125: while (!EMPTY_LIST(n->ackl[queue]))
! 126: ospf_send_lsack_(p, n, queue);
! 127: }
! 128:
! 129: void
! 130: ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
! 131: struct ospf_neighbor *n)
! 132: {
! 133: struct ospf_proto *p = ifa->oa->po;
! 134: struct ospf_lsa_header lsa, *lsas;
! 135: struct top_hash_entry *ret, *en;
! 136: uint i, lsa_count;
! 137: u32 lsa_type, lsa_domain;
! 138:
! 139: /* RFC 2328 13.7 */
! 140:
! 141: /* No need to check length, lsack has only basic header */
! 142:
! 143: OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from nbr %R on %s", n->rid, ifa->ifname);
! 144:
! 145: if (n->state < NEIGHBOR_EXCHANGE)
! 146: {
! 147: OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange");
! 148: return;
! 149: }
! 150:
! 151: ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
! 152:
! 153: ospf_lsack_body(p, pkt, &lsas, &lsa_count);
! 154: for (i = 0; i < lsa_count; i++)
! 155: {
! 156: lsa_ntoh_hdr(&lsas[i], &lsa);
! 157: lsa_get_type_domain(&lsa, n->ifa, &lsa_type, &lsa_domain);
! 158:
! 159: ret = ospf_hash_find(n->lsrth, lsa_domain, lsa.id, lsa.rt, lsa_type);
! 160: if (!ret)
! 161: continue;
! 162:
! 163: if (lsa_comp(&lsa, &ret->lsa) != CMP_SAME)
! 164: {
! 165: OSPF_TRACE(D_PACKETS, "Strange LSACK from nbr %R on %s", n->rid, ifa->ifname);
! 166: OSPF_TRACE(D_PACKETS, " Type: %04x, Id: %R, Rt: %R",
! 167: lsa_type, lsa.id, lsa.rt);
! 168: OSPF_TRACE(D_PACKETS, " I have: Seq: %08x, Age: %4u, Sum: %04x",
! 169: ret->lsa.sn, ret->lsa.age, ret->lsa.checksum);
! 170: OSPF_TRACE(D_PACKETS, " It has: Seq: %08x, Age: %4u, Sum: %04x",
! 171: lsa.sn, lsa.age, lsa.checksum);
! 172: continue;
! 173: }
! 174:
! 175: DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
! 176: lsa_type, lsa.id, lsa.rt, n->rid);
! 177:
! 178: en = ospf_hash_find_entry(p->gr, ret);
! 179: ospf_lsa_lsrt_down_(en, n, ret);
! 180: }
! 181: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>