]>
Commit | Line | Data |
---|---|---|
de769e24 OF |
1 | /* |
2 | * BIRD -- OSPF | |
3 | * | |
c76ba51a | 4 | * (c) 2000-2004 Ondrej Filip <feela@network.cz> |
de769e24 OF |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #include "ospf.h" | |
10 | ||
c3226991 OZ |
11 | |
12 | struct ospf_lsack_packet | |
13 | { | |
14 | struct ospf_packet ospf_packet; | |
15 | struct ospf_lsa_header lsh[]; | |
16 | }; | |
17 | ||
18 | ||
fb9bf688 | 19 | char *s_queue[] = { "direct", "delayed" }; |
67315ef6 | 20 | |
8298d780 OZ |
21 | |
22 | static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt) | |
23 | { | |
24 | struct ospf_packet *op = &pkt->ospf_packet; | |
25 | ||
26 | ASSERT(op->type == LSACK_P); | |
27 | ospf_dump_common(p, op); | |
28 | ||
a6bc04d5 | 29 | unsigned int i, j; |
8298d780 OZ |
30 | j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) / |
31 | sizeof(struct ospf_lsa_header); | |
32 | ||
33 | for (i = 0; i < j; i++) | |
c3226991 | 34 | ospf_dump_lsahdr(p, pkt->lsh + i); |
8298d780 OZ |
35 | } |
36 | ||
37 | ||
c76ba51a OF |
38 | /* |
39 | * ===================================== | |
40 | * Note, that h is in network endianity! | |
41 | * ===================================== | |
42 | */ | |
fb9bf688 | 43 | |
67315ef6 | 44 | void |
fb9bf688 | 45 | ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h, |
8e15e048 | 46 | int queue) |
67315ef6 | 47 | { |
8e15e048 | 48 | struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n)); |
fb9bf688 | 49 | memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header)); |
c76ba51a | 50 | add_tail(&n->ackl[queue], NODE no); |
3aab39f5 OZ |
51 | DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n", s_queue[queue], |
52 | n->rid, ntohl(h->id), ntohl(h->rt), h->type); | |
67315ef6 OF |
53 | } |
54 | ||
67315ef6 | 55 | void |
c76ba51a | 56 | ospf_lsack_send(struct ospf_neighbor *n, int queue) |
67315ef6 OF |
57 | { |
58 | struct ospf_packet *op; | |
59 | struct ospf_lsack_packet *pk; | |
fb9bf688 | 60 | u16 len, i = 0; |
67315ef6 OF |
61 | struct ospf_lsa_header *h; |
62 | struct lsah_n *no; | |
fb9bf688 | 63 | struct ospf_iface *ifa = n->ifa; |
86c84d76 | 64 | struct proto *p = &n->ifa->oa->po->proto; |
67315ef6 | 65 | |
fb9bf688 OF |
66 | if (EMPTY_LIST(n->ackl[queue])) |
67 | return; | |
c76ba51a | 68 | |
e7b76b97 | 69 | pk = ospf_tx_buffer(ifa); |
353729f5 | 70 | op = &pk->ospf_packet; |
67315ef6 | 71 | |
3e2bd0f1 | 72 | ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P); |
c3226991 | 73 | h = pk->lsh; |
67315ef6 | 74 | |
fb9bf688 | 75 | while (!EMPTY_LIST(n->ackl[queue])) |
67315ef6 | 76 | { |
fb9bf688 OF |
77 | no = (struct lsah_n *) HEAD(n->ackl[queue]); |
78 | memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header)); | |
69fbf9a2 | 79 | DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id), |
3aab39f5 | 80 | ntohl((h + i)->rt), (h + i)->type); |
69fbf9a2 | 81 | i++; |
023f5e86 | 82 | rem_node(NODE no); |
284c43ff | 83 | mb_free(no); |
fb9bf688 | 84 | if ((i * sizeof(struct ospf_lsa_header) + |
3e2bd0f1 | 85 | sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa)) |
67315ef6 | 86 | { |
fb9bf688 | 87 | if (!EMPTY_LIST(n->ackl[queue])) |
67315ef6 | 88 | { |
fb9bf688 OF |
89 | len = |
90 | sizeof(struct ospf_lsack_packet) + | |
91 | i * sizeof(struct ospf_lsa_header); | |
92 | op->length = htons(len); | |
fb9bf688 | 93 | DBG("Sending and continuing! Len=%u\n", len); |
8298d780 | 94 | |
353729f5 | 95 | OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name); |
8298d780 | 96 | |
fb9bf688 | 97 | if (ifa->type == OSPF_IT_BCAST) |
67315ef6 | 98 | { |
fb9bf688 | 99 | if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) |
95127cbb OZ |
100 | ospf_send_to_all(ifa); |
101 | else if (ifa->cf->real_bcast) | |
102 | ospf_send_to_bdr(ifa); | |
67315ef6 | 103 | else |
f9c799a0 | 104 | ospf_send_to(ifa, AllDRouters); |
67315ef6 OF |
105 | } |
106 | else | |
107 | { | |
fb9bf688 | 108 | if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) |
f9c799a0 | 109 | ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); |
eb436e16 | 110 | else |
f9c799a0 | 111 | ospf_send_to_bdr(ifa); |
67315ef6 | 112 | } |
284c43ff | 113 | |
3e2bd0f1 | 114 | ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P); |
fb9bf688 | 115 | i = 0; |
67315ef6 OF |
116 | } |
117 | } | |
118 | } | |
119 | ||
fb9bf688 OF |
120 | len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header); |
121 | op->length = htons(len); | |
fb9bf688 | 122 | DBG("Sending! Len=%u\n", len); |
8298d780 | 123 | |
353729f5 | 124 | OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name); |
8298d780 | 125 | |
fb9bf688 | 126 | if (ifa->type == OSPF_IT_BCAST) |
67315ef6 | 127 | { |
fb9bf688 | 128 | if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP)) |
95127cbb OZ |
129 | ospf_send_to_all(ifa); |
130 | else if (ifa->cf->real_bcast) | |
131 | ospf_send_to_bdr(ifa); | |
67315ef6 | 132 | else |
f9c799a0 | 133 | ospf_send_to(ifa, AllDRouters); |
67315ef6 OF |
134 | } |
135 | else | |
f9c799a0 | 136 | ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE); |
de769e24 OF |
137 | } |
138 | ||
139 | void | |
c3226991 OZ |
140 | ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, |
141 | struct ospf_neighbor *n) | |
de769e24 | 142 | { |
a6bc04d5 | 143 | struct proto *p = &ifa->oa->po->proto; |
c3226991 | 144 | struct ospf_lsa_header lsa; |
4bf41ac8 | 145 | struct top_hash_entry *en; |
a6bc04d5 OZ |
146 | unsigned int i, lsano; |
147 | ||
148 | unsigned int size = ntohs(ps_i->length); | |
149 | if (size < sizeof(struct ospf_lsack_packet)) | |
150 | { | |
151 | log(L_ERR "Bad OSPF LSACK packet from %I - too short (%u B)", n->ip, size); | |
152 | return; | |
153 | } | |
ebff007f | 154 | |
a6bc04d5 | 155 | struct ospf_lsack_packet *ps = (void *) ps_i; |
8298d780 OZ |
156 | OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->iface->name); |
157 | ||
4bb9ce56 | 158 | ospf_neigh_sm(n, INM_HELLOREC); |
9669362f | 159 | |
fb9bf688 OF |
160 | if (n->state < NEIGHBOR_EXCHANGE) |
161 | return; | |
9669362f | 162 | |
a6bc04d5 | 163 | lsano = (size - sizeof(struct ospf_lsack_packet)) / |
4bf41ac8 | 164 | sizeof(struct ospf_lsa_header); |
a6bc04d5 | 165 | for (i = 0; i < lsano; i++) |
4bf41ac8 | 166 | { |
c3226991 | 167 | ntohlsah(ps->lsh + i, &lsa); |
b49e6f5a OZ |
168 | u32 dom = ospf_lsa_domain(lsa.type, n->ifa); |
169 | if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL) | |
2e10a170 | 170 | continue; /* pg 155 */ |
4bf41ac8 | 171 | |
9b7de4c4 | 172 | if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */ |
4bf41ac8 | 173 | { |
fb9bf688 OF |
174 | if ((lsa.sn == LSA_MAXSEQNO) && (lsa.age == LSA_MAXAGE)) |
175 | continue; | |
37282678 | 176 | |
34a877cc OZ |
177 | OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip); |
178 | OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R", | |
179 | lsa.type, lsa.id, lsa.rt); | |
180 | OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x", | |
fb9bf688 | 181 | en->lsa.age, en->lsa.sn, en->lsa.checksum); |
34a877cc | 182 | OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x", |
fb9bf688 | 183 | lsa.age, lsa.sn, lsa.checksum); |
4bf41ac8 OF |
184 | continue; |
185 | } | |
186 | ||
3aab39f5 OZ |
187 | DBG("Deleting LS Id: %R RT: %R Type: %u from LS Retl for neighbor %R\n", |
188 | lsa.id, lsa.rt, lsa.type, n->rid); | |
4bf41ac8 | 189 | s_rem_node(SNODE en); |
fb9bf688 OF |
190 | ospf_hash_delete(n->lsrth, en); |
191 | } | |
de769e24 | 192 | } |