LQ messages are now processed. MPRs are selected based on the link
[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.3 2004/11/05 20:58:10 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
133   // initialize the static fields
134
135   lq_tc->comm.type = LQ_TC_MESSAGE;
136   lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
137   lq_tc->comm.size = 0;
138
139   COPY_IP(&lq_tc->comm.orig, &main_addr);
140
141   lq_tc->comm.ttl = MAX_TTL;
142   lq_tc->comm.hops = 0;
143   lq_tc->comm.seqno = get_msg_seqno();
144
145   COPY_IP(&lq_tc->from, &main_addr);
146
147   lq_tc->ansn = ansn;
148
149   lq_tc->neigh = NULL;
150  
151   // loop through all neighbours
152   
153   for(i = 0; i < HASHSIZE; i++)
154     {
155       for(walker = neighbortable[i].next; walker != &neighbortable[i];
156           walker = walker->next)
157         {
158           // only consider symmetric neighbours
159
160           if(walker->status != SYM)
161             continue;
162
163           // TC redundancy == 1: only consider MPRs and MPR selectors
164
165           if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
166               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
167             continue;
168
169           // TC redundancy == 0: only consider MPR selectors
170
171           else if (olsr_cnf->tc_redundancy == 0 &&
172                    olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
173             continue;
174
175           // allocate a neighbour entry
176           
177           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor), "Build LQ_TC");
178                 
179           // set the entry's main address
180
181           COPY_IP(&neigh->main, &walker->neighbor_main_addr);
182
183           // set the entry's link quality
184
185           neigh->link_quality =
186             olsr_neighbor_best_link_quality(&neigh->main);
187
188           // queue the neighbour entry
189
190           neigh->next = lq_tc->neigh;
191           lq_tc->neigh = neigh;
192         }
193     }
194 }
195
196 static void
197 destroy_lq_tc(struct lq_tc_message *lq_tc)
198 {
199   struct lq_tc_neighbor *walker, *aux;
200
201   // loop through the queued neighbour entries and free them
202
203   for (walker = lq_tc->neigh; walker != NULL; walker = aux)
204     {
205       aux = walker->next;
206       free(walker);
207     }
208 }
209
210 static int common_size(void)
211 {
212   // return the size of the header shared by all OLSR messages
213
214   return (olsr_cnf->ip_version == AF_INET) ?
215     sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
216 }
217
218 static void serialize_common(struct olsr_common *comm)
219 {
220   struct olsr_header_v4 *olsr_head_v4;
221   struct olsr_header_v6 *olsr_head_v6;
222
223   // serialize an IPv4 OLSR message header
224
225   if (olsr_cnf->ip_version == AF_INET)
226     {
227       olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
228
229       olsr_head_v4->type = comm->type;
230       olsr_head_v4->vtime = double_to_me(comm->vtime);
231       olsr_head_v4->size = htons(comm->size);
232
233       COPY_IP(&olsr_head_v4->orig, &comm->orig);
234
235       olsr_head_v4->ttl = comm->ttl;
236       olsr_head_v4->hops = comm->hops;
237       olsr_head_v4->seqno = htons(comm->seqno);
238     }
239
240   // serialize an IPv6 OLSR message header
241
242   olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
243
244   olsr_head_v6->type = comm->type;
245   olsr_head_v6->vtime = double_to_me(comm->vtime);
246   olsr_head_v6->size = htons(comm->size);
247
248   COPY_IP(&olsr_head_v6->orig, &comm->orig);
249
250   olsr_head_v6->ttl = comm->ttl;
251   olsr_head_v6->hops = comm->hops;
252   olsr_head_v6->seqno = htons(comm->seqno);
253 }
254
255 static void
256 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
257 {
258   int off, rem, size, req;
259   struct lq_hello_header *head;
260   struct lq_hello_info_header *info_head;
261   struct lq_hello_neighbor *neigh;
262   unsigned char *buff;
263   int is_first;
264   int i, j;
265
266   if (lq_hello == NULL || outif == NULL)
267     return;
268
269   // leave space for the OLSR header
270
271   off = common_size();
272
273   // initialize the LQ_HELLO header
274
275   head = (struct lq_hello_header *)(msg_buffer + off);
276
277   head->reserved = 0;
278   head->htime = double_to_me(lq_hello->htime);
279   head->will = lq_hello->will; 
280
281   // 'off' is the offset of the byte following the LQ_HELLO header
282
283   off += sizeof (struct lq_hello_header);
284
285   // our work buffer starts at 'off'...
286
287   buff = msg_buffer + off;
288
289   // ... that's why we start with a 'size' of 0 and subtract 'off' from
290   // the remaining bytes in the output buffer
291
292   size = 0;
293   rem = net_outbuffer_bytes_left(outif) - off;
294
295   // initially, we want to put at least an info header, an IP address,
296   // and the corresponding link quality into the message
297
298   if (rem < sizeof (struct lq_hello_info_header) + ipsize + 4)
299   {
300     net_output(outif);
301
302     rem = net_outbuffer_bytes_left(outif) - off;
303   }
304
305   info_head = NULL;
306
307   // iterate through all neighbor types ('i') and all link types ('j')
308
309   for (i = 0; i <= MAX_NEIGH; i++) 
310     {
311       for(j = 0; j <= MAX_LINK; j++)
312         {
313           if(j == HIDE_LINK)
314             continue;
315
316           is_first = 1;
317
318           // loop through neighbors
319
320           for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
321             {  
322               if (neigh->neigh_type != i || neigh->link_type != j)
323                 continue;
324
325               // we need space for an IP address plus link quality
326               // information
327
328               req = ipsize + 4;
329
330               // no, we also need space for an info header, as this is the
331               // first neighbor with the current neighor type and link type
332
333               if (is_first != 0)
334                 req += sizeof (struct lq_hello_info_header);
335
336               // we do not have enough space left
337
338               if (size + req > rem)
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                   // finalize the info header
347
348                   info_head->size =
349                     ntohs(buff + size - (unsigned char *)info_head);
350                               
351                   // output packet
352
353                   net_outbuffer_push(outif, msg_buffer, size + off);
354
355                   net_output(outif);
356
357                   // move to the beginning of the buffer
358
359                   size = 0;
360                   rem = net_outbuffer_bytes_left(outif) - off;
361
362                   // we need a new info header
363
364                   is_first = 1;
365                 }
366
367               // create a new info header
368
369               if (is_first != 0)
370                 {
371                   info_head = (struct lq_hello_info_header *)(buff + size);
372                   size += sizeof (struct lq_hello_info_header);
373
374                   info_head->reserved = 0;
375                   info_head->link_code = CREATE_LINK_CODE(i, j);
376                 }
377
378               // add the current neighbor's IP address
379
380               COPY_IP(buff + size, &neigh->addr);
381               size += ipsize;
382
383               // add the corresponding link quality
384
385               buff[size++] = (unsigned char)(neigh->link_quality * 256);
386               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 256);
387
388               // pad
389
390               buff[size++] = 0;
391               buff[size++] = 0;
392
393               is_first = 0;
394             }
395
396           // finalize the info header, if there are any neighbors with the
397           // current neighbor type and link type
398
399           if (is_first == 0)
400             info_head->size = ntohs(buff + size - (unsigned char *)info_head);
401         }
402     }
403
404   // finalize the OLSR header
405
406   lq_hello->comm.size = size + off;
407
408   serialize_common((struct olsr_common *)lq_hello);
409
410   // move the message to the output buffer
411
412   net_outbuffer_push(outif, msg_buffer, size + off);
413 }
414
415 static void
416 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
417 {
418   int off, rem, size;
419   struct lq_tc_header *head;
420   struct lq_tc_neighbor *neigh;
421   unsigned char *buff;
422
423   if (lq_tc == NULL || outif == NULL)
424     return;
425
426   // leave space for the OLSR header
427
428   off = common_size();
429
430   // initialize the LQ_TC header
431
432   head = (struct lq_tc_header *)(msg_buffer + off);
433
434   head->ansn = htons(lq_tc->ansn);
435   head->reserved = 0;
436
437   // 'off' is the offset of the byte following the LQ_TC header
438
439   off += sizeof (struct lq_tc_header);
440
441   // our work buffer starts at 'off'...
442
443   buff = msg_buffer + off;
444
445   // ... that's why we start with a 'size' of 0 and subtract 'off' from
446   // the remaining bytes in the output buffer
447
448   size = 0;
449   rem = net_outbuffer_bytes_left(outif) - off;
450
451   // initially, we want to put at least an IP address and the corresponding
452   // link quality into the message
453
454   if (rem < ipsize + 4)
455   {
456     net_output(outif);
457
458     rem = net_outbuffer_bytes_left(outif) - off;
459   }
460
461   // loop through neighbors
462
463   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
464     {  
465       // we need space for an IP address plus link quality
466       // information
467
468       if (size + ipsize + 4 > rem)
469         {
470           // finalize the OLSR header
471
472           lq_tc->comm.size = size + off;
473
474           serialize_common((struct olsr_common *)lq_tc);
475
476           // output packet
477
478           net_outbuffer_push(outif, msg_buffer, size + off);
479
480           net_output(outif);
481
482           // move to the beginning of the buffer
483
484           size = 0;
485           rem = net_outbuffer_bytes_left(outif) - off;
486         }
487
488       // add the current neighbor's IP address
489
490       COPY_IP(buff + size, &neigh->main);
491       size += ipsize;
492
493       // add the corresponding link quality
494
495       buff[size++] = (unsigned char)(neigh->link_quality * 256);
496
497       // pad
498
499       buff[size++] = 0;
500       buff[size++] = 0;
501       buff[size++] = 0;
502     }
503
504   // finalize the OLSR header
505
506   lq_tc->comm.size = size + off;
507
508   serialize_common((struct olsr_common *)lq_tc);
509
510   net_outbuffer_push(outif, msg_buffer, size + off);
511 }
512
513 static void *deserialize_common(struct olsr_common *comm, void *ser)
514 {
515   struct olsr_header_v4 *olsr_head_v4;
516   struct olsr_header_v6 *olsr_head_v6;
517
518   // deserialize an IPv4 OLSR message header
519
520   if (olsr_cnf->ip_version == AF_INET)
521     {
522       olsr_head_v4 = (struct olsr_header_v4 *)ser;
523
524       comm->type = olsr_head_v4->type;
525       comm->vtime = me_to_double(olsr_head_v4->vtime);
526       comm->size = ntohs(olsr_head_v4->size);
527
528       COPY_IP(&comm->orig, &olsr_head_v4->orig);
529
530       comm->ttl = olsr_head_v4->ttl;
531       comm->hops = olsr_head_v4->hops;
532       comm->seqno = ntohs(olsr_head_v4->seqno);
533
534       return (void *)(olsr_head_v4 + 1);
535     }
536
537   // deserialize an IPv6 OLSR message header
538
539   olsr_head_v6 = (struct olsr_header_v6 *)ser;
540
541   comm->type = olsr_head_v6->type;
542   comm->vtime = me_to_double(olsr_head_v6->vtime);
543   comm->size = ntohs(olsr_head_v6->size);
544
545   COPY_IP(&comm->orig, &olsr_head_v6->orig);
546
547   comm->ttl = olsr_head_v6->ttl;
548   comm->hops = olsr_head_v6->hops;
549   comm->seqno = ntohs(olsr_head_v6->seqno);
550
551   return (void *)(olsr_head_v6 + 1);
552 }
553
554 static void
555 deserialize_lq_hello(struct lq_hello_message *lq_hello, void *ser)
556 {
557   struct lq_hello_header *head;
558   struct lq_hello_info_header *info_head;
559   unsigned char *curr, *limit, *limit2;
560   struct lq_hello_neighbor *neigh;
561   
562   lq_hello->neigh = NULL;
563
564   if (ser == NULL)
565     return;
566
567   head = (struct lq_hello_header *)
568     deserialize_common((struct olsr_common *)lq_hello, ser);
569
570   if (lq_hello->comm.type != LQ_HELLO_MESSAGE)
571     return;
572
573   limit = ((unsigned char *)ser) + lq_hello->comm.size;
574
575   lq_hello->htime = me_to_double(head->htime);
576   lq_hello->will = head->will;
577
578   curr = (unsigned char *)(head + 1);
579
580   while (curr < limit)
581     {
582       info_head = (struct lq_hello_info_header *)curr;
583
584       limit2 = curr + ntohs(info_head->size);
585
586       curr = (unsigned char *)(info_head + 1);
587       
588       while (curr < limit2)
589         {
590           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
591                               "LQ_HELLO deserialization");
592
593           COPY_IP(&neigh->addr, curr);
594           curr += ipsize;
595
596           neigh->link_quality = (double)*curr++ / 256.0;
597           neigh->neigh_link_quality = (double)*curr++ / 256.0;
598
599           curr += 2;
600
601           neigh->link_type = EXTRACT_LINK(info_head->link_code);
602           neigh->neigh_type = EXTRACT_STATUS(info_head->link_code);
603
604           neigh->next = lq_hello->neigh;
605           lq_hello->neigh = neigh;
606         }
607     }
608 }
609
610 static void
611 deserialize_lq_tc(struct lq_tc_message *lq_tc, void *ser,
612                   union olsr_ip_addr *from)
613 {
614   struct lq_tc_header *head;
615   union olsr_ip_addr *addr;
616   unsigned char *curr, *limit;
617   struct lq_tc_neighbor *neigh;
618
619   lq_tc->neigh = NULL;
620
621   if (ser == NULL)
622     return;
623
624   head = (struct lq_tc_header *)
625     deserialize_common((struct olsr_common *)lq_tc, ser);
626
627   if (lq_tc->comm.type != LQ_TC_MESSAGE)
628     return;
629
630   limit = ((unsigned char *)ser) + lq_tc->comm.size;
631
632   addr = mid_lookup_main_addr(from);
633
634   if (addr == 0)
635     COPY_IP(&lq_tc->from, from);
636
637   else
638     COPY_IP(&lq_tc->from, addr);
639
640   lq_tc->ansn =  ntohs(head->ansn);
641
642   curr = (unsigned char *)(head + 1);
643
644   while (curr < limit)
645     {
646       neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
647                           "LQ_TC deserialization");
648
649       COPY_IP(&neigh->main, curr);
650       curr += ipsize;
651
652       neigh->link_quality = (double)*curr / 256.0;
653       curr += 4;
654
655       neigh->next = lq_tc->neigh;
656       lq_tc->neigh = neigh;
657     }
658 }
659
660 void
661 olsr_output_lq_hello(void *para)
662 {
663   struct lq_hello_message lq_hello;
664   struct interface *outif = (struct interface *)para;
665
666   // create LQ_HELLO in internal format
667
668   create_lq_hello(&lq_hello, outif);
669
670   // convert internal format into transmission format, send it
671
672   serialize_lq_hello(&lq_hello, outif);
673
674   // destroy internal format
675
676   destroy_lq_hello(&lq_hello);
677
678   if(net_output_pending(outif))
679     net_output(outif);
680 }
681
682 void
683 olsr_output_lq_tc(void *para)
684 {
685   static int prev_empty = 1;
686   struct lq_tc_message lq_tc;
687   struct interface *outif = (struct interface *)para;
688   struct timeval timer;
689
690   // create LQ_TC in internal format
691
692   create_lq_tc(&lq_tc, outif);
693
694   // a) the message is not empty
695
696   if (lq_tc.neigh != NULL)
697     {
698       prev_empty = 0;
699
700       // convert internal format into transmission format, send it
701
702       serialize_lq_tc(&lq_tc, outif);
703     }
704
705   // b) this is the first empty message
706
707   else if (prev_empty == 0)
708     {
709       // initialize timer
710
711       olsr_init_timer((olsr_u32_t)(max_tc_vtime * 3) * 1000, &timer);
712       timeradd(&now, &timer, &send_empty_tc);
713
714       prev_empty = 1;
715
716       // convert internal format into transmission format, send it
717
718       serialize_lq_tc(&lq_tc, outif);
719     }
720
721   // c) this is not the first empty message, send if timer hasn't fired
722
723   else if (!TIMED_OUT(&send_empty_tc))
724     serialize_lq_tc(&lq_tc, outif);
725
726   // destroy internal format
727
728   destroy_lq_tc(&lq_tc);
729
730   if(net_output_pending(outif) && TIMED_OUT(&fwdtimer[outif->if_nr]))
731     set_buffer_timer(outif);
732 }
733
734 static void
735 process_lq_hello(struct lq_hello_message *lq_hello, struct interface *inif,
736                  union olsr_ip_addr *from)
737 {
738   struct hello_message hello;
739   struct lq_hello_neighbor *neigh;
740   struct hello_neighbor *new_neigh;
741
742   // XXX - translation is ugly; everybody should use lq_hello_message :-)
743
744   // move the static fields from LQ_HELLO to HELLO
745
746   hello.vtime = lq_hello->comm.vtime;
747   hello.htime = lq_hello->htime;
748
749   COPY_IP(&hello.source_addr, &lq_hello->comm.orig);
750
751   hello.packet_seq_number = lq_hello->comm.seqno;
752   hello.hop_count = lq_hello->comm.hops;
753   hello.ttl = lq_hello->comm.ttl;
754   hello.willingness = lq_hello->will;
755
756   // move all LQ_HELLO neighbours to HELLO
757
758   for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
759     {
760       // allocate HELLO neighbour
761
762       new_neigh = olsr_malloc(sizeof (struct hello_neighbor),
763                               "LQ_HELLO translation");
764
765       // copy fields
766
767       new_neigh->status = neigh->neigh_type;
768       new_neigh->link = neigh->link_type;
769       new_neigh->link_quality = neigh->link_quality;
770
771       COPY_IP(&new_neigh->address, &neigh->addr);
772
773       // queue HELLO neighbour
774
775       new_neigh->next = hello.neighbors;
776       hello.neighbors = new_neigh;
777     }
778
779   olsr_hello_tap(&hello, inif, from);
780 }
781
782 static void
783 process_lq_tc(struct lq_tc_message *lq_tc, struct interface *inif,
784               union olsr_ip_addr *from, union olsr_message *ser)
785 {
786   struct tc_message tc;
787   struct lq_tc_neighbor *neigh;
788   struct tc_mpr_addr *new_neigh;
789
790   // XXX - translation is ugly; everybody should use lq_tc_message :-)
791
792   // move the static fields from LQ_TC to TC
793
794   tc.vtime = lq_tc->comm.vtime;
795
796   COPY_IP(&tc.source_addr, &lq_tc->from);
797   COPY_IP(&tc.originator, &lq_tc->comm.orig);
798
799   tc.packet_seq_number = lq_tc->comm.seqno;
800   tc.hop_count = lq_tc->comm.hops;
801   tc.ttl = lq_tc->comm.ttl;
802   tc.ansn = lq_tc->ansn;
803
804   // move all LQ_TC neighbours to TC
805
806   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
807     {
808       // allocate TC neighbour
809
810       new_neigh = olsr_malloc(sizeof (struct tc_mpr_addr),
811                               "LQ_TC translation");
812
813       // copy fields
814
815       new_neigh->link_quality = neigh->link_quality;
816
817       COPY_IP(&new_neigh->address, &neigh->main);
818
819       // queue TC neighbour
820
821       new_neigh->next = tc.multipoint_relay_selector_address;
822       tc.multipoint_relay_selector_address = new_neigh;
823     }
824
825   olsr_tc_tap(&tc, inif, from, ser);
826 }
827
828 void
829 olsr_input_lq_hello(union olsr_message *ser,
830                     struct interface *inif,
831                     union olsr_ip_addr *from)
832 {
833   struct lq_hello_message lq_hello;
834
835   // convert received packet from transmission format into internal format
836
837   deserialize_lq_hello(&lq_hello, ser);
838
839   // process internal format
840
841   process_lq_hello(&lq_hello, inif, from);
842
843   // destroy internal format
844
845   destroy_lq_hello(&lq_hello);
846 }
847
848 void
849 olsr_input_lq_tc(union olsr_message *ser, struct interface *inif,
850                  union olsr_ip_addr *from)
851 {
852   struct lq_tc_message lq_tc;
853   
854   // convert received packet from transmission format into internal format
855
856   deserialize_lq_tc(&lq_tc, ser, from);
857
858   // process internal format
859
860   process_lq_tc(&lq_tc, inif, from, ser);
861
862   // destroy internal format
863
864   destroy_lq_tc(&lq_tc);
865 }
866 #endif