]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/lsack.c
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.
8 * Can be freely distributed and used under the terms of the GNU GPL.
15 struct ospf_lsack_packet
17 struct ospf_packet hdr;
18 // union ospf_auth auth;
20 struct ospf_lsa_header lsas[];
27 struct ospf_lsa_header lsa
;
32 ospf_lsack_body(struct ospf_proto
*p
, struct ospf_packet
*pkt
,
33 struct ospf_lsa_header
**body
, uint
*count
)
35 uint plen
= ntohs(pkt
->length
);
36 uint hlen
= ospf_pkt_hdrlen(p
);
38 *body
= ((void *) pkt
) + hlen
;
39 *count
= (plen
- hlen
) / sizeof(struct ospf_lsa_header
);
43 ospf_dump_lsack(struct ospf_proto
*p
, struct ospf_packet
*pkt
)
45 struct ospf_lsa_header
*lsas
;
48 ASSERT(pkt
->type
== LSACK_P
);
49 ospf_dump_common(p
, pkt
);
51 ospf_lsack_body(p
, pkt
, &lsas
, &lsa_count
);
52 for (i
= 0; i
< lsa_count
; i
++)
53 ospf_dump_lsahdr(p
, lsas
+ i
);
58 ospf_enqueue_lsack(struct ospf_neighbor
*n
, struct ospf_lsa_header
*h_n
, int queue
)
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
);
70 ospf_reset_lsack_queue(struct ospf_neighbor
*n
)
74 WALK_LIST_FIRST(no
, n
->ackl
[ACKL_DELAY
])
82 ospf_send_lsack_(struct ospf_proto
*p
, struct ospf_neighbor
*n
, int queue
)
84 struct ospf_iface
*ifa
= n
->ifa
;
85 struct ospf_lsa_header
*lsas
;
86 struct ospf_packet
*pkt
;
88 uint i
, lsa_max
, length
;
92 pkt
= ospf_tx_buffer(ifa
);
93 ospf_pkt_fill_hdr(ifa
, pkt
, LSACK_P
);
94 ospf_lsack_body(p
, pkt
, &lsas
, &lsa_max
);
96 for (i
= 0; i
< lsa_max
&& !EMPTY_LIST(n
->ackl
[queue
]); i
++)
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
);
106 length
= ospf_pkt_hdrlen(p
) + i
* sizeof(struct ospf_lsa_header
);
107 pkt
->length
= htons(length
);
109 OSPF_PACKET(ospf_dump_lsack
, pkt
, "LSACK packet sent via %s", ifa
->ifname
);
111 if (ifa
->type
== OSPF_IT_BCAST
)
113 if ((ifa
->state
== OSPF_IS_DR
) || (ifa
->state
== OSPF_IS_BACKUP
))
114 ospf_send_to_all(ifa
);
116 ospf_send_to_des(ifa
);
119 ospf_send_to_agt(ifa
, NEIGHBOR_EXCHANGE
);
123 ospf_send_lsack(struct ospf_proto
*p
, struct ospf_neighbor
*n
, int queue
)
125 while (!EMPTY_LIST(n
->ackl
[queue
]))
126 ospf_send_lsack_(p
, n
, queue
);
130 ospf_receive_lsack(struct ospf_packet
*pkt
, struct ospf_iface
*ifa
,
131 struct ospf_neighbor
*n
)
133 struct ospf_proto
*p
= ifa
->oa
->po
;
134 struct ospf_lsa_header lsa
, *lsas
;
135 struct top_hash_entry
*ret
, *en
;
137 u32 lsa_type
, lsa_domain
;
141 /* No need to check length, lsack has only basic header */
143 OSPF_PACKET(ospf_dump_lsack
, pkt
, "LSACK packet received from nbr %R on %s", n
->rid
, ifa
->ifname
);
145 if (n
->state
< NEIGHBOR_EXCHANGE
)
147 OSPF_TRACE(D_PACKETS
, "LSACK packet ignored - lesser state than Exchange");
151 ospf_neigh_sm(n
, INM_HELLOREC
); /* Not in RFC */
153 ospf_lsack_body(p
, pkt
, &lsas
, &lsa_count
);
154 for (i
= 0; i
< lsa_count
; i
++)
156 lsa_ntoh_hdr(&lsas
[i
], &lsa
);
157 lsa_get_type_domain(&lsa
, n
->ifa
, &lsa_type
, &lsa_domain
);
159 ret
= ospf_hash_find(n
->lsrth
, lsa_domain
, lsa
.id
, lsa
.rt
, lsa_type
);
163 if (lsa_comp(&lsa
, &ret
->lsa
) != CMP_SAME
)
165 OSPF_TRACE(D_PACKETS
, "Strange LSACK from %I", n
->ip
);
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: Age: %4u, Seq: %08x, Sum: %04x",
169 ret
->lsa
.age
, ret
->lsa
.sn
, ret
->lsa
.checksum
);
170 OSPF_TRACE(D_PACKETS
, "He has: Age: %4u, Seq: %08x, Sum: %04x",
171 lsa
.age
, lsa
.sn
, lsa
.checksum
);
175 en
= ospf_hash_find_entry(p
->gr
, ret
);
179 DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
180 lsa_type
, lsa
.id
, lsa
.rt
, n
->rid
);
181 s_rem_node(SNODE ret
);
182 ospf_hash_delete(n
->lsrth
, ret
);