remove local tc/mid/hna timer from win32 code
[olsrd.git] / src / lq_packet.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "ipcalc.h"
43 #include "olsr_protocol.h"
44 #include "defs.h"
45 #include "lq_packet.h"
46 #include "interfaces.h"
47 #include "link_set.h"
48 #include "neighbor_table.h"
49 #include "mid_set.h"
50 #include "olsr_time.h"
51 #include "process_package.h"    // XXX - remove
52 #include "olsr.h"
53 #include "net_olsr.h"
54 #include "lq_plugin.h"
55 #include "olsr_logging.h"
56
57 #include <stdlib.h>
58
59 bool lq_tc_pending = false;
60
61 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
62
63 static uint16_t local_ansn_number = 0;
64
65 uint16_t get_local_ansn_number(bool increase) {
66   if (increase)
67     local_ansn_number++;
68   return local_ansn_number;
69 }
70
71
72 static void
73 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
74 {
75   struct link_entry *walker;
76
77   // initialize the static fields
78
79   lq_hello->comm.type = olsr_get_Hello_MessageId();
80   lq_hello->comm.vtime = outif->hello_validity;
81   lq_hello->comm.size = 0;
82
83   lq_hello->comm.orig = olsr_cnf->router_id;
84
85   lq_hello->comm.ttl = 1;
86   lq_hello->comm.hops = 0;
87
88   lq_hello->htime = outif->hello_interval;
89   lq_hello->will = olsr_cnf->willingness;
90
91   lq_hello->neigh = NULL;
92
93   // loop through the link set
94
95   OLSR_FOR_ALL_LINK_ENTRIES(walker) {
96
97     // allocate a neighbour entry
98     struct lq_hello_neighbor *neigh = olsr_malloc_lq_hello_neighbor();
99
100     // a) this neighbor interface IS NOT visible via the output interface
101     if (olsr_ipcmp(&walker->local_iface_addr, &outif->ip_addr) != 0)
102       neigh->link_type = UNSPEC_LINK;
103
104     // b) this neighbor interface IS visible via the output interface
105
106     else
107       neigh->link_type = lookup_link_status(walker);
108
109     // set the entry's link quality
110     olsr_copy_hello_lq(neigh, walker);
111
112     // set the entry's neighbour type
113
114     if (walker->neighbor->is_mpr)
115       neigh->neigh_type = MPR_NEIGH;
116
117     else if (walker->neighbor->is_sym)
118       neigh->neigh_type = SYM_NEIGH;
119
120     else
121       neigh->neigh_type = NOT_NEIGH;
122
123     // set the entry's neighbour interface address
124
125     neigh->addr = walker->neighbor_iface_addr;
126
127     // queue the neighbour entry
128     neigh->next = lq_hello->neigh;
129     lq_hello->neigh = neigh;
130
131   }
132   OLSR_FOR_ALL_LINK_ENTRIES_END(walker);
133 }
134
135 void
136 destroy_lq_hello(struct lq_hello_message *lq_hello)
137 {
138   struct lq_hello_neighbor *walker, *aux;
139
140   // loop through the queued neighbour entries and free them
141
142   for (walker = lq_hello->neigh; walker != NULL; walker = aux) {
143     aux = walker->next;
144     olsr_free_lq_hello_neighbor(walker);
145   }
146
147   lq_hello->neigh = NULL;
148 }
149
150 static int
151 common_size(void)
152 {
153   // return the size of the header shared by all OLSR messages
154
155   return (olsr_cnf->ip_version == AF_INET) ? sizeof(struct olsr_header_v4) : sizeof(struct olsr_header_v6);
156 }
157
158 static void
159 serialize_common(struct olsr_common *comm)
160 {
161   if (olsr_cnf->ip_version == AF_INET) {
162     // serialize an IPv4 OLSR message header
163     struct olsr_header_v4 *olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
164
165     olsr_head_v4->type = comm->type;
166     olsr_head_v4->vtime = reltime_to_me(comm->vtime);
167     olsr_head_v4->size = htons(comm->size);
168
169     olsr_head_v4->orig = comm->orig.v4.s_addr;
170
171     olsr_head_v4->ttl = comm->ttl;
172     olsr_head_v4->hops = comm->hops;
173     olsr_head_v4->seqno = htons(get_msg_seqno());
174   } else {
175     // serialize an IPv6 OLSR message header
176     struct olsr_header_v6 *olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
177
178     olsr_head_v6->type = comm->type;
179     olsr_head_v6->vtime = reltime_to_me(comm->vtime);
180     olsr_head_v6->size = htons(comm->size);
181
182     memcpy(&olsr_head_v6->orig, &comm->orig.v6.s6_addr, sizeof(olsr_head_v6->orig));
183
184     olsr_head_v6->ttl = comm->ttl;
185     olsr_head_v6->hops = comm->hops;
186     olsr_head_v6->seqno = htons(get_msg_seqno());
187   }
188 }
189
190 static void
191 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
192 {
193   static const int LINK_ORDER[] = { SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK };
194   int rem, size, req, expected_size = 0;
195   struct lq_hello_info_header *info_head;
196   struct lq_hello_neighbor *neigh;
197   unsigned char *buff;
198   bool is_first;
199   int i;
200
201   // leave space for the OLSR header
202   int off = common_size();
203
204   // initialize the LQ_HELLO header
205
206   struct lq_hello_header *head = (struct lq_hello_header *)(msg_buffer + off);
207
208   head->reserved = 0;
209   head->htime = reltime_to_me(lq_hello->htime);
210   head->will = lq_hello->will;
211
212   // 'off' is the offset of the byte following the LQ_HELLO header
213
214   off += sizeof(struct lq_hello_header);
215
216   // our work buffer starts at 'off'...
217
218   buff = msg_buffer + off;
219
220   // ... that's why we start with a 'size' of 0 and subtract 'off' from
221   // the remaining bytes in the output buffer
222
223   size = 0;
224   rem = net_outbuffer_bytes_left(outif) - off;
225
226   /*
227    * Initially, we want to put the complete lq_hello into the message.
228    * For this flush the output buffer (if there are some bytes in).
229    * This is a hack/fix, which prevents message fragementation resulting
230    * in instable links. The ugly lq/genmsg code should be reworked anyhow.
231    */
232   if (0 < net_output_pending(outif)) {
233     for (i = 0; i <= MAX_NEIGH; i++) {
234       unsigned int j;
235       for (j = 0; j < ARRAYSIZE(LINK_ORDER); j++) {
236         is_first = true;
237         for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next) {
238           if (0 == i && 0 == j)
239             expected_size += olsr_cnf->ipsize + olsr_sizeof_TCLQ();
240           if (neigh->neigh_type == i && neigh->link_type == LINK_ORDER[j]) {
241             if (is_first) {
242               expected_size += sizeof(struct lq_hello_info_header);
243               is_first = false;
244             }
245           }
246         }
247       }
248     }
249   }
250
251   if (rem < expected_size) {
252     net_output(outif);
253     rem = net_outbuffer_bytes_left(outif) - off;
254   }
255
256   info_head = NULL;
257
258   // iterate through all neighbor types ('i') and all link types ('j')
259
260   for (i = 0; i <= MAX_NEIGH; i++) {
261     unsigned int j;
262     for (j = 0; j < ARRAYSIZE(LINK_ORDER); j++) {
263       is_first = true;
264
265       // loop through neighbors
266
267       for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next) {
268         if (neigh->neigh_type != i || neigh->link_type != LINK_ORDER[j])
269           continue;
270
271         // we need space for an IP address plus link quality
272         // information
273
274         req = olsr_cnf->ipsize + 4;
275
276         // no, we also need space for an info header, as this is the
277         // first neighbor with the current neighor type and link type
278
279         if (is_first)
280           req += sizeof(struct lq_hello_info_header);
281
282         // we do not have enough space left
283
284         // force signed comparison
285
286         if ((int)(size + req) > rem) {
287           // finalize the OLSR header
288
289           lq_hello->comm.size = size + off;
290
291           serialize_common(&lq_hello->comm);
292
293           // finalize the info header
294
295           info_head->size = ntohs(buff + size - (unsigned char *)info_head);
296
297           // output packet
298
299           net_outbuffer_push(outif, msg_buffer, size + off);
300
301           net_output(outif);
302
303           // move to the beginning of the buffer
304
305           size = 0;
306           rem = net_outbuffer_bytes_left(outif) - off;
307
308           // we need a new info header
309
310           is_first = true;
311         }
312         // create a new info header
313
314         if (is_first) {
315           info_head = (struct lq_hello_info_header *)(buff + size);
316           size += sizeof(struct lq_hello_info_header);
317
318           info_head->reserved = 0;
319           info_head->link_code = CREATE_LINK_CODE(i, LINK_ORDER[j]);
320         }
321         // add the current neighbor's IP address
322
323         genipcopy(buff + size, &neigh->addr);
324         size += olsr_cnf->ipsize;
325
326         // add the corresponding link quality
327         size += olsr_serialize_hello_lq_pair(&buff[size], neigh);
328
329         is_first = false;
330       }
331
332       // finalize the info header, if there are any neighbors with the
333       // current neighbor type and link type
334
335       if (!is_first)
336         info_head->size = ntohs(buff + size - (unsigned char *)info_head);
337     }
338   }
339
340   // finalize the OLSR header
341
342   lq_hello->comm.size = size + off;
343
344   serialize_common((struct olsr_common *)lq_hello);
345
346   // move the message to the output buffer
347
348   net_outbuffer_push(outif, msg_buffer, size + off);
349 }
350
351 void
352 olsr_output_lq_hello(void *para)
353 {
354   struct lq_hello_message lq_hello;
355   struct interface *outif = para;
356
357   if (outif == NULL) {
358     return;
359   }
360   // create LQ_HELLO in internal format
361   create_lq_hello(&lq_hello, outif);
362
363   // convert internal format into transmission format, send it
364   serialize_lq_hello(&lq_hello, outif);
365
366   // destroy internal format
367   destroy_lq_hello(&lq_hello);
368
369   if (net_output_pending(outif)) {
370     if (outif->immediate_send_tc) {
371       set_buffer_timer(outif);
372     } else {
373       net_output(outif);
374     }
375   }
376 }
377 /*
378  * Local Variables:
379  * c-basic-offset: 2
380  * indent-tabs-mode: nil
381  * End:
382  */