Process LQ_TC messages. Made link quality features configurable. Set
[olsrd.git] / src / lq_packet.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
4  * Copyright (C) 2004 Thomas Lopatic (thomas@lopatic.de)
5  *
6  * This file is part of the olsr.org OLSR daemon.
7  *
8  * olsr.org is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * olsr.org is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with olsr.org; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  * 
22  * 
23  * $Id: lq_packet.c,v 1.4 2004/11/07 20:09:11 tlopatic Exp $
24  *
25  */
26
27 #if defined USE_LINK_QUALITY
28 #include "olsr_protocol.h"
29 #include "defs.h"
30 #include "interfaces.h"
31 #include "link_set.h"
32 #include "neighbor_table.h"
33 #include "mpr_selector_set.h"
34 #include "mid_set.h"
35 #include "mantissa.h"
36 #include "process_package.h" // XXX - remove
37 #include "two_hop_neighbor_table.h"
38 #include "hysteresis.h"
39
40 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
41
42 static void
43 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
44 {
45   struct lq_hello_neighbor *neigh;
46   struct link_entry *walker;
47
48   // initialize the static fields
49
50   lq_hello->comm.type = LQ_HELLO_MESSAGE;
51   lq_hello->comm.vtime = me_to_double(outif->valtimes.hello);
52   lq_hello->comm.size = 0;
53
54   COPY_IP(&lq_hello->comm.orig, &main_addr);
55
56   lq_hello->comm.ttl = 1;
57   lq_hello->comm.hops = 0;
58   lq_hello->comm.seqno = get_msg_seqno();
59
60   lq_hello->htime = me_to_double(outif->hello_etime);
61   lq_hello->will = olsr_cnf->willingness;
62
63   lq_hello->neigh = NULL;
64   
65   // loop through the link set
66
67   for (walker = link_set; walker != NULL; walker = walker->next)
68     {
69       // allocate a neighbour entry
70
71       neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
72       
73       // a) this neighbor interface IS NOT visible via the output interface
74
75       if(!COMP_IP(&walker->local_iface_addr, &outif->ip_addr))
76         neigh->link_type = UNSPEC_LINK;
77       
78       // b) this neighbor interface IS visible via the output interface
79
80       else
81         neigh->link_type = lookup_link_status(walker);
82
83       // set the entry's link quality
84
85       neigh->link_quality = walker->loss_link_quality;
86       neigh->neigh_link_quality = walker->neigh_link_quality;
87
88       // set the entry's neighbour type
89
90       if(walker->neighbor->is_mpr)
91         neigh->neigh_type = MPR_NEIGH;
92
93       else if (walker->neighbor->status == SYM)
94         neigh->neigh_type = SYM_NEIGH;
95
96       else if (walker->neighbor->status == NOT_SYM)
97         neigh->neigh_type = NOT_NEIGH;
98   
99       // set the entry's neighbour interface address
100
101       COPY_IP(&neigh->addr, &walker->neighbor_iface_addr);
102       
103       // queue the neighbour entry
104
105       neigh->next = lq_hello->neigh;
106       lq_hello->neigh = neigh;
107     }
108 }
109
110 static void
111 destroy_lq_hello(struct lq_hello_message *lq_hello)
112 {
113   struct lq_hello_neighbor *walker, *aux;
114
115   // loop through the queued neighbour entries and free them
116
117   for (walker = lq_hello->neigh; walker != NULL; walker = aux)
118     {
119       aux = walker->next;
120       free(walker);
121     }
122
123   lq_hello->neigh = NULL;
124 }
125
126 static void
127 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
128 {
129   struct lq_tc_neighbor *neigh;
130   int i;
131   struct neighbor_entry *walker;
132   struct link_entry *link;
133
134   // initialize the static fields
135
136   lq_tc->comm.type = LQ_TC_MESSAGE;
137   lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
138   lq_tc->comm.size = 0;
139
140   COPY_IP(&lq_tc->comm.orig, &main_addr);
141
142   lq_tc->comm.ttl = MAX_TTL;
143   lq_tc->comm.hops = 0;
144   lq_tc->comm.seqno = get_msg_seqno();
145
146   COPY_IP(&lq_tc->from, &main_addr);
147
148   lq_tc->ansn = ansn;
149
150   lq_tc->neigh = NULL;
151  
152   // loop through all neighbours
153   
154   for(i = 0; i < HASHSIZE; i++)
155     {
156       for(walker = neighbortable[i].next; walker != &neighbortable[i];
157           walker = walker->next)
158         {
159           // only consider symmetric neighbours
160
161           if(walker->status != SYM)
162             continue;
163
164           // TC redundancy == 1: only consider MPRs and MPR selectors
165
166           if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
167               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
168             continue;
169
170           // TC redundancy == 0: only consider MPR selectors
171
172           else if (olsr_cnf->tc_redundancy == 0 &&
173                    olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
174             continue;
175
176           // allocate a neighbour entry
177           
178           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor), "Build LQ_TC");
179                 
180           // set the entry's main address
181
182           COPY_IP(&neigh->main, &walker->neighbor_main_addr);
183
184           // set the entry's link quality
185
186           link = olsr_neighbor_best_inverse_link(&neigh->main);
187           neigh->link_quality = link->loss_link_quality;
188
189           link = olsr_neighbor_best_link(&neigh->main);
190           neigh->neigh_link_quality = link->neigh_link_quality;
191
192           // queue the neighbour entry
193
194           neigh->next = lq_tc->neigh;
195           lq_tc->neigh = neigh;
196         }
197     }
198 }
199
200 static void
201 destroy_lq_tc(struct lq_tc_message *lq_tc)
202 {
203   struct lq_tc_neighbor *walker, *aux;
204
205   // loop through the queued neighbour entries and free them
206
207   for (walker = lq_tc->neigh; walker != NULL; walker = aux)
208     {
209       aux = walker->next;
210       free(walker);
211     }
212 }
213
214 static int common_size(void)
215 {
216   // return the size of the header shared by all OLSR messages
217
218   return (olsr_cnf->ip_version == AF_INET) ?
219     sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
220 }
221
222 static void serialize_common(struct olsr_common *comm)
223 {
224   struct olsr_header_v4 *olsr_head_v4;
225   struct olsr_header_v6 *olsr_head_v6;
226
227   // serialize an IPv4 OLSR message header
228
229   if (olsr_cnf->ip_version == AF_INET)
230     {
231       olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
232
233       olsr_head_v4->type = comm->type;
234       olsr_head_v4->vtime = double_to_me(comm->vtime);
235       olsr_head_v4->size = htons(comm->size);
236
237       COPY_IP(&olsr_head_v4->orig, &comm->orig);
238
239       olsr_head_v4->ttl = comm->ttl;
240       olsr_head_v4->hops = comm->hops;
241       olsr_head_v4->seqno = htons(comm->seqno);
242     }
243
244   // serialize an IPv6 OLSR message header
245
246   olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
247
248   olsr_head_v6->type = comm->type;
249   olsr_head_v6->vtime = double_to_me(comm->vtime);
250   olsr_head_v6->size = htons(comm->size);
251
252   COPY_IP(&olsr_head_v6->orig, &comm->orig);
253
254   olsr_head_v6->ttl = comm->ttl;
255   olsr_head_v6->hops = comm->hops;
256   olsr_head_v6->seqno = htons(comm->seqno);
257 }
258
259 static void
260 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
261 {
262   int off, rem, size, req;
263   struct lq_hello_header *head;
264   struct lq_hello_info_header *info_head;
265   struct lq_hello_neighbor *neigh;
266   unsigned char *buff;
267   int is_first;
268   int i, j;
269
270   if (lq_hello == NULL || outif == NULL)
271     return;
272
273   // leave space for the OLSR header
274
275   off = common_size();
276
277   // initialize the LQ_HELLO header
278
279   head = (struct lq_hello_header *)(msg_buffer + off);
280
281   head->reserved = 0;
282   head->htime = double_to_me(lq_hello->htime);
283   head->will = lq_hello->will; 
284
285   // 'off' is the offset of the byte following the LQ_HELLO header
286
287   off += sizeof (struct lq_hello_header);
288
289   // our work buffer starts at 'off'...
290
291   buff = msg_buffer + off;
292
293   // ... that's why we start with a 'size' of 0 and subtract 'off' from
294   // the remaining bytes in the output buffer
295
296   size = 0;
297   rem = net_outbuffer_bytes_left(outif) - off;
298
299   // initially, we want to put at least an info header, an IP address,
300   // and the corresponding link quality into the message
301
302   if (rem < sizeof (struct lq_hello_info_header) + ipsize + 4)
303   {
304     net_output(outif);
305
306     rem = net_outbuffer_bytes_left(outif) - off;
307   }
308
309   info_head = NULL;
310
311   // iterate through all neighbor types ('i') and all link types ('j')
312
313   for (i = 0; i <= MAX_NEIGH; i++) 
314     {
315       for(j = 0; j <= MAX_LINK; j++)
316         {
317           if(j == HIDE_LINK)
318             continue;
319
320           is_first = 1;
321
322           // loop through neighbors
323
324           for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
325             {  
326               if (neigh->neigh_type != i || neigh->link_type != j)
327                 continue;
328
329               // we need space for an IP address plus link quality
330               // information
331
332               req = ipsize + 4;
333
334               // no, we also need space for an info header, as this is the
335               // first neighbor with the current neighor type and link type
336
337               if (is_first != 0)
338                 req += sizeof (struct lq_hello_info_header);
339
340               // we do not have enough space left
341
342               if (size + req > rem)
343                 {
344                   // finalize the OLSR header
345
346                   lq_hello->comm.size = size + off;
347
348                   serialize_common((struct olsr_common *)lq_hello);
349
350                   // finalize the info header
351
352                   info_head->size =
353                     ntohs(buff + size - (unsigned char *)info_head);
354                               
355                   // output packet
356
357                   net_outbuffer_push(outif, msg_buffer, size + off);
358
359                   net_output(outif);
360
361                   // move to the beginning of the buffer
362
363                   size = 0;
364                   rem = net_outbuffer_bytes_left(outif) - off;
365
366                   // we need a new info header
367
368                   is_first = 1;
369                 }
370
371               // create a new info header
372
373               if (is_first != 0)
374                 {
375                   info_head = (struct lq_hello_info_header *)(buff + size);
376                   size += sizeof (struct lq_hello_info_header);
377
378                   info_head->reserved = 0;
379                   info_head->link_code = CREATE_LINK_CODE(i, j);
380                 }
381
382               // add the current neighbor's IP address
383
384               COPY_IP(buff + size, &neigh->addr);
385               size += ipsize;
386
387               // add the corresponding link quality
388
389               buff[size++] = (unsigned char)(neigh->link_quality * 256);
390               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 256);
391
392               // pad
393
394               buff[size++] = 0;
395               buff[size++] = 0;
396
397               is_first = 0;
398             }
399
400           // finalize the info header, if there are any neighbors with the
401           // current neighbor type and link type
402
403           if (is_first == 0)
404             info_head->size = ntohs(buff + size - (unsigned char *)info_head);
405         }
406     }
407
408   // finalize the OLSR header
409
410   lq_hello->comm.size = size + off;
411
412   serialize_common((struct olsr_common *)lq_hello);
413
414   // move the message to the output buffer
415
416   net_outbuffer_push(outif, msg_buffer, size + off);
417 }
418
419 static void
420 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
421 {
422   int off, rem, size;
423   struct lq_tc_header *head;
424   struct lq_tc_neighbor *neigh;
425   unsigned char *buff;
426
427   if (lq_tc == NULL || outif == NULL)
428     return;
429
430   // leave space for the OLSR header
431
432   off = common_size();
433
434   // initialize the LQ_TC header
435
436   head = (struct lq_tc_header *)(msg_buffer + off);
437
438   head->ansn = htons(lq_tc->ansn);
439   head->reserved = 0;
440
441   // 'off' is the offset of the byte following the LQ_TC header
442
443   off += sizeof (struct lq_tc_header);
444
445   // our work buffer starts at 'off'...
446
447   buff = msg_buffer + off;
448
449   // ... that's why we start with a 'size' of 0 and subtract 'off' from
450   // the remaining bytes in the output buffer
451
452   size = 0;
453   rem = net_outbuffer_bytes_left(outif) - off;
454
455   // initially, we want to put at least an IP address and the corresponding
456   // link quality into the message
457
458   if (rem < ipsize + 4)
459   {
460     net_output(outif);
461
462     rem = net_outbuffer_bytes_left(outif) - off;
463   }
464
465   // loop through neighbors
466
467   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
468     {  
469       // we need space for an IP address plus link quality
470       // information
471
472       if (size + ipsize + 4 > rem)
473         {
474           // finalize the OLSR header
475
476           lq_tc->comm.size = size + off;
477
478           serialize_common((struct olsr_common *)lq_tc);
479
480           // output packet
481
482           net_outbuffer_push(outif, msg_buffer, size + off);
483
484           net_output(outif);
485
486           // move to the beginning of the buffer
487
488           size = 0;
489           rem = net_outbuffer_bytes_left(outif) - off;
490         }
491
492       // add the current neighbor's IP address
493
494       COPY_IP(buff + size, &neigh->main);
495       size += ipsize;
496
497       // add the corresponding link quality
498
499       buff[size++] = (unsigned char)(neigh->link_quality * 256);
500       buff[size++] = (unsigned char)(neigh->neigh_link_quality * 256);
501
502       // pad
503
504       buff[size++] = 0;
505       buff[size++] = 0;
506     }
507
508   // finalize the OLSR header
509
510   lq_tc->comm.size = size + off;
511
512   serialize_common((struct olsr_common *)lq_tc);
513
514   net_outbuffer_push(outif, msg_buffer, size + off);
515 }
516
517 static void *deserialize_common(struct olsr_common *comm, void *ser)
518 {
519   struct olsr_header_v4 *olsr_head_v4;
520   struct olsr_header_v6 *olsr_head_v6;
521
522   // deserialize an IPv4 OLSR message header
523
524   if (olsr_cnf->ip_version == AF_INET)
525     {
526       olsr_head_v4 = (struct olsr_header_v4 *)ser;
527
528       comm->type = olsr_head_v4->type;
529       comm->vtime = me_to_double(olsr_head_v4->vtime);
530       comm->size = ntohs(olsr_head_v4->size);
531
532       COPY_IP(&comm->orig, &olsr_head_v4->orig);
533
534       comm->ttl = olsr_head_v4->ttl;
535       comm->hops = olsr_head_v4->hops;
536       comm->seqno = ntohs(olsr_head_v4->seqno);
537
538       return (void *)(olsr_head_v4 + 1);
539     }
540
541   // deserialize an IPv6 OLSR message header
542
543   olsr_head_v6 = (struct olsr_header_v6 *)ser;
544
545   comm->type = olsr_head_v6->type;
546   comm->vtime = me_to_double(olsr_head_v6->vtime);
547   comm->size = ntohs(olsr_head_v6->size);
548
549   COPY_IP(&comm->orig, &olsr_head_v6->orig);
550
551   comm->ttl = olsr_head_v6->ttl;
552   comm->hops = olsr_head_v6->hops;
553   comm->seqno = ntohs(olsr_head_v6->seqno);
554
555   return (void *)(olsr_head_v6 + 1);
556 }
557
558 static void
559 deserialize_lq_hello(struct lq_hello_message *lq_hello, void *ser)
560 {
561   struct lq_hello_header *head;
562   struct lq_hello_info_header *info_head;
563   unsigned char *curr, *limit, *limit2;
564   struct lq_hello_neighbor *neigh;
565   
566   lq_hello->neigh = NULL;
567
568   if (ser == NULL)
569     return;
570
571   head = (struct lq_hello_header *)
572     deserialize_common((struct olsr_common *)lq_hello, ser);
573
574   if (lq_hello->comm.type != LQ_HELLO_MESSAGE)
575     return;
576
577   limit = ((unsigned char *)ser) + lq_hello->comm.size;
578
579   lq_hello->htime = me_to_double(head->htime);
580   lq_hello->will = head->will;
581
582   curr = (unsigned char *)(head + 1);
583
584   while (curr < limit)
585     {
586       info_head = (struct lq_hello_info_header *)curr;
587
588       limit2 = curr + ntohs(info_head->size);
589
590       curr = (unsigned char *)(info_head + 1);
591       
592       while (curr < limit2)
593         {
594           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
595                               "LQ_HELLO deserialization");
596
597           COPY_IP(&neigh->addr, curr);
598           curr += ipsize;
599
600           neigh->link_quality = (double)*curr++ / 256.0;
601           neigh->neigh_link_quality = (double)*curr++ / 256.0;
602
603           curr += 2;
604
605           neigh->link_type = EXTRACT_LINK(info_head->link_code);
606           neigh->neigh_type = EXTRACT_STATUS(info_head->link_code);
607
608           neigh->next = lq_hello->neigh;
609           lq_hello->neigh = neigh;
610         }
611     }
612 }
613
614 static void
615 deserialize_lq_tc(struct lq_tc_message *lq_tc, void *ser,
616                   union olsr_ip_addr *from)
617 {
618   struct lq_tc_header *head;
619   union olsr_ip_addr *addr;
620   unsigned char *curr, *limit;
621   struct lq_tc_neighbor *neigh;
622
623   lq_tc->neigh = NULL;
624
625   if (ser == NULL)
626     return;
627
628   head = (struct lq_tc_header *)
629     deserialize_common((struct olsr_common *)lq_tc, ser);
630
631   if (lq_tc->comm.type != LQ_TC_MESSAGE)
632     return;
633
634   limit = ((unsigned char *)ser) + lq_tc->comm.size;
635
636   addr = mid_lookup_main_addr(from);
637
638   if (addr == 0)
639     COPY_IP(&lq_tc->from, from);
640
641   else
642     COPY_IP(&lq_tc->from, addr);
643
644   lq_tc->ansn =  ntohs(head->ansn);
645
646   curr = (unsigned char *)(head + 1);
647
648   while (curr < limit)
649     {
650       neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
651                           "LQ_TC deserialization");
652
653       COPY_IP(&neigh->main, curr);
654       curr += ipsize;
655
656       neigh->link_quality = (double)*curr++ / 256.0;
657       neigh->neigh_link_quality = (double)*curr++ / 256.0;
658
659       curr += 2;
660
661       neigh->next = lq_tc->neigh;
662       lq_tc->neigh = neigh;
663     }
664 }
665
666 void
667 olsr_output_lq_hello(void *para)
668 {
669   struct lq_hello_message lq_hello;
670   struct interface *outif = (struct interface *)para;
671
672   // create LQ_HELLO in internal format
673
674   create_lq_hello(&lq_hello, outif);
675
676   // convert internal format into transmission format, send it
677
678   serialize_lq_hello(&lq_hello, outif);
679
680   // destroy internal format
681
682   destroy_lq_hello(&lq_hello);
683
684   if(net_output_pending(outif))
685     net_output(outif);
686 }
687
688 void
689 olsr_output_lq_tc(void *para)
690 {
691   static int prev_empty = 1;
692   struct lq_tc_message lq_tc;
693   struct interface *outif = (struct interface *)para;
694   struct timeval timer;
695
696   // create LQ_TC in internal format
697
698   create_lq_tc(&lq_tc, outif);
699
700   // a) the message is not empty
701
702   if (lq_tc.neigh != NULL)
703     {
704       prev_empty = 0;
705
706       // convert internal format into transmission format, send it
707
708       serialize_lq_tc(&lq_tc, outif);
709     }
710
711   // b) this is the first empty message
712
713   else if (prev_empty == 0)
714     {
715       // initialize timer
716
717       olsr_init_timer((olsr_u32_t)(max_tc_vtime * 3) * 1000, &timer);
718       timeradd(&now, &timer, &send_empty_tc);
719
720       prev_empty = 1;
721
722       // convert internal format into transmission format, send it
723
724       serialize_lq_tc(&lq_tc, outif);
725     }
726
727   // c) this is not the first empty message, send if timer hasn't fired
728
729   else if (!TIMED_OUT(&send_empty_tc))
730     serialize_lq_tc(&lq_tc, outif);
731
732   // destroy internal format
733
734   destroy_lq_tc(&lq_tc);
735
736   if(net_output_pending(outif) && TIMED_OUT(&fwdtimer[outif->if_nr]))
737     set_buffer_timer(outif);
738 }
739
740 static void
741 process_lq_hello(struct lq_hello_message *lq_hello, struct interface *inif,
742                  union olsr_ip_addr *from)
743 {
744   struct hello_message hello;
745   struct lq_hello_neighbor *neigh;
746   struct hello_neighbor *new_neigh;
747
748   // XXX - translation is ugly; everybody should use lq_hello_message :-)
749
750   // move the static fields from LQ_HELLO to HELLO
751
752   hello.vtime = lq_hello->comm.vtime;
753   hello.htime = lq_hello->htime;
754
755   COPY_IP(&hello.source_addr, &lq_hello->comm.orig);
756
757   hello.packet_seq_number = lq_hello->comm.seqno;
758   hello.hop_count = lq_hello->comm.hops;
759   hello.ttl = lq_hello->comm.ttl;
760   hello.willingness = lq_hello->will;
761
762   // move all LQ_HELLO neighbours to HELLO
763
764   for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
765     {
766       // allocate HELLO neighbour
767
768       new_neigh = olsr_malloc(sizeof (struct hello_neighbor),
769                               "LQ_HELLO translation");
770
771       // copy fields
772
773       new_neigh->status = neigh->neigh_type;
774       new_neigh->link = neigh->link_type;
775       new_neigh->link_quality = neigh->link_quality;
776
777       COPY_IP(&new_neigh->address, &neigh->addr);
778
779       // queue HELLO neighbour
780
781       new_neigh->next = hello.neighbors;
782       hello.neighbors = new_neigh;
783     }
784
785   olsr_hello_tap(&hello, inif, from);
786 }
787
788 static void
789 process_lq_tc(struct lq_tc_message *lq_tc, struct interface *inif,
790               union olsr_ip_addr *from, union olsr_message *ser)
791 {
792   struct tc_message tc;
793   struct lq_tc_neighbor *neigh;
794   struct tc_mpr_addr *new_neigh;
795
796   // XXX - translation is ugly; everybody should use lq_tc_message :-)
797
798   // move the static fields from LQ_TC to TC
799
800   tc.vtime = lq_tc->comm.vtime;
801
802   COPY_IP(&tc.source_addr, &lq_tc->from);
803   COPY_IP(&tc.originator, &lq_tc->comm.orig);
804
805   tc.packet_seq_number = lq_tc->comm.seqno;
806   tc.hop_count = lq_tc->comm.hops;
807   tc.ttl = lq_tc->comm.ttl;
808   tc.ansn = lq_tc->ansn;
809
810   // move all LQ_TC neighbours to TC
811
812   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
813     {
814       // allocate TC neighbour
815
816       new_neigh = olsr_malloc(sizeof (struct tc_mpr_addr),
817                               "LQ_TC translation");
818
819       // copy fields
820
821       new_neigh->link_quality = neigh->link_quality;
822       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
823
824       COPY_IP(&new_neigh->address, &neigh->main);
825
826       // queue TC neighbour
827
828       new_neigh->next = tc.multipoint_relay_selector_address;
829       tc.multipoint_relay_selector_address = new_neigh;
830     }
831
832   olsr_tc_tap(&tc, inif, from, ser);
833 }
834
835 void
836 olsr_input_lq_hello(union olsr_message *ser,
837                     struct interface *inif,
838                     union olsr_ip_addr *from)
839 {
840   struct lq_hello_message lq_hello;
841
842   // convert received packet from transmission format into internal format
843
844   deserialize_lq_hello(&lq_hello, ser);
845
846   // process internal format
847
848   process_lq_hello(&lq_hello, inif, from);
849
850   // destroy internal format
851
852   destroy_lq_hello(&lq_hello);
853 }
854
855 void
856 olsr_input_lq_tc(union olsr_message *ser, struct interface *inif,
857                  union olsr_ip_addr *from)
858 {
859   struct lq_tc_message lq_tc;
860   
861   // convert received packet from transmission format into internal format
862
863   deserialize_lq_tc(&lq_tc, ser, from);
864
865   // process internal format
866
867   process_lq_tc(&lq_tc, inif, from, ser);
868
869   // destroy internal format
870
871   destroy_lq_tc(&lq_tc);
872 }
873 #endif