Return to lsack.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / ospf |
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: if (queue == ACKL_DIRECT) ! 110: { ! 111: OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet sent to nbr %R on %s", n->rid, ifa->ifname); ! 112: ospf_send_to(ifa, n->ip); ! 113: return; ! 114: } ! 115: ! 116: OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet sent via %s", ifa->ifname); ! 117: ! 118: if (ifa->type == OSPF_IT_BCAST) ! 119: { ! 120: if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) ! 121: ospf_send_to_all(ifa); ! 122: else ! 123: ospf_send_to_des(ifa); ! 124: } ! 125: else ! 126: ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); ! 127: } ! 128: ! 129: void ! 130: ospf_send_lsack(struct ospf_proto *p, struct ospf_neighbor *n, int queue) ! 131: { ! 132: while (!EMPTY_LIST(n->ackl[queue])) ! 133: ospf_send_lsack_(p, n, queue); ! 134: } ! 135: ! 136: void ! 137: ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa, ! 138: struct ospf_neighbor *n) ! 139: { ! 140: struct ospf_proto *p = ifa->oa->po; ! 141: struct ospf_lsa_header lsa, *lsas; ! 142: struct top_hash_entry *ret, *en; ! 143: uint i, lsa_count; ! 144: u32 lsa_type, lsa_domain; ! 145: ! 146: /* RFC 2328 13.7 */ ! 147: ! 148: /* No need to check length, lsack has only basic header */ ! 149: ! 150: OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from nbr %R on %s", n->rid, ifa->ifname); ! 151: ! 152: if (n->state < NEIGHBOR_EXCHANGE) ! 153: { ! 154: OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange"); ! 155: return; ! 156: } ! 157: ! 158: ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */ ! 159: ! 160: ospf_lsack_body(p, pkt, &lsas, &lsa_count); ! 161: for (i = 0; i < lsa_count; i++) ! 162: { ! 163: lsa_ntoh_hdr(&lsas[i], &lsa); ! 164: lsa_get_type_domain(&lsa, n->ifa, &lsa_type, &lsa_domain); ! 165: ! 166: ret = ospf_hash_find(n->lsrth, lsa_domain, lsa.id, lsa.rt, lsa_type); ! 167: if (!ret) ! 168: continue; ! 169: ! 170: if (lsa_comp(&lsa, &ret->lsa) != CMP_SAME) ! 171: { ! 172: OSPF_TRACE(D_PACKETS, "Strange LSACK from nbr %R on %s", n->rid, ifa->ifname); ! 173: OSPF_TRACE(D_PACKETS, " Type: %04x, Id: %R, Rt: %R", ! 174: lsa_type, lsa.id, lsa.rt); ! 175: OSPF_TRACE(D_PACKETS, " I have: Seq: %08x, Age: %4u, Sum: %04x", ! 176: ret->lsa.sn, ret->lsa.age, ret->lsa.checksum); ! 177: OSPF_TRACE(D_PACKETS, " It has: Seq: %08x, Age: %4u, Sum: %04x", ! 178: lsa.sn, lsa.age, lsa.checksum); ! 179: continue; ! 180: } ! 181: ! 182: DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n", ! 183: lsa_type, lsa.id, lsa.rt, n->rid); ! 184: ! 185: en = ospf_hash_find_entry(p->gr, ret); ! 186: ospf_lsa_lsrt_down_(en, n, ret); ! 187: } ! 188: }