aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2013-04-23 09:39:57 -0400
committerAntonio Quartulli <antonio@meshcoding.com>2013-10-09 15:22:26 -0400
commitef26157747d42254453f6b3ac2bd8bd3c53339c3 (patch)
treeac9f366de417ca89b225143eb176b9618376f5eb
parent60cf7981b770e329a05734d1e6eb055f13219202 (diff)
batman-adv: tvlv - basic infrastructure
The goal is to provide the infrastructure for sending, receiving and parsing information 'containers' while preserving backward compatibility. TVLV (based on the commonly known Type Length Value technique) was chosen as the format for those containers. Even if a node does not know the tvlv type of a certain container it can simply skip the current container and proceed with the next. Past experience has shown features evolve over time, so a 'version' field was added right from the start to allow differentiating between feature variants - hence the name: T(ype) V(ersion) L(ength) V(alue). This patch introduces the basic TVLV infrastructure: * register / unregister tvlv containers to be sent with each OGM (on primary interfaces only) * register / unregister callback handlers to be called upon finding the corresponding tvlv type in a tvlv buffer * unicast tvlv send / receive API calls Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Spyros Gasteratos <morfeas3000@gmail.com> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
-rw-r--r--net/batman-adv/bat_iv_ogm.c38
-rw-r--r--net/batman-adv/main.c575
-rw-r--r--net/batman-adv/main.h35
-rw-r--r--net/batman-adv/packet.h41
-rw-r--r--net/batman-adv/routing.c48
-rw-r--r--net/batman-adv/routing.h2
-rw-r--r--net/batman-adv/types.h72
7 files changed, 794 insertions, 17 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 0a8a80cd4bf1..f7dd7e51fff4 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -207,12 +207,12 @@ static uint8_t batadv_hop_penalty(uint8_t tq,
207 207
208/* is there another aggregated packet here? */ 208/* is there another aggregated packet here? */
209static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, 209static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
210 int tt_num_changes) 210 __be16 tvlv_len)
211{ 211{
212 int next_buff_pos = 0; 212 int next_buff_pos = 0;
213 213
214 next_buff_pos += buff_pos + BATADV_OGM_HLEN; 214 next_buff_pos += buff_pos + BATADV_OGM_HLEN;
215 next_buff_pos += batadv_tt_len(tt_num_changes); 215 next_buff_pos += ntohs(tvlv_len);
216 216
217 return (next_buff_pos <= packet_len) && 217 return (next_buff_pos <= packet_len) &&
218 (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); 218 (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
@@ -240,7 +240,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
240 240
241 /* adjust all flags and log packets */ 241 /* adjust all flags and log packets */
242 while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, 242 while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
243 batadv_ogm_packet->tt_num_changes)) { 243 batadv_ogm_packet->tvlv_len)) {
244 /* we might have aggregated direct link packets with an 244 /* we might have aggregated direct link packets with an
245 * ordinary base packet 245 * ordinary base packet
246 */ 246 */
@@ -267,7 +267,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
267 hard_iface->net_dev->dev_addr); 267 hard_iface->net_dev->dev_addr);
268 268
269 buff_pos += BATADV_OGM_HLEN; 269 buff_pos += BATADV_OGM_HLEN;
270 buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); 270 buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
271 packet_num++; 271 packet_num++;
272 packet_pos = forw_packet->skb->data + buff_pos; 272 packet_pos = forw_packet->skb->data + buff_pos;
273 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; 273 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
@@ -601,7 +601,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
601 struct batadv_hard_iface *if_incoming) 601 struct batadv_hard_iface *if_incoming)
602{ 602{
603 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); 603 struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
604 uint8_t tt_num_changes; 604 uint16_t tvlv_len;
605 605
606 if (batadv_ogm_packet->header.ttl <= 1) { 606 if (batadv_ogm_packet->header.ttl <= 1) {
607 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n"); 607 batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
@@ -621,7 +621,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
621 return; 621 return;
622 } 622 }
623 623
624 tt_num_changes = batadv_ogm_packet->tt_num_changes; 624 tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
625 625
626 batadv_ogm_packet->header.ttl--; 626 batadv_ogm_packet->header.ttl--;
627 memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); 627 memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
@@ -642,7 +642,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
642 batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK; 642 batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
643 643
644 batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet, 644 batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet,
645 BATADV_OGM_HLEN + batadv_tt_len(tt_num_changes), 645 BATADV_OGM_HLEN + tvlv_len,
646 if_incoming, 0, batadv_iv_ogm_fwd_send_time()); 646 if_incoming, 0, batadv_iv_ogm_fwd_send_time());
647} 647}
648 648
@@ -691,16 +691,18 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
691 int vis_server, tt_num_changes = 0; 691 int vis_server, tt_num_changes = 0;
692 uint32_t seqno; 692 uint32_t seqno;
693 uint8_t bandwidth; 693 uint8_t bandwidth;
694 uint16_t tvlv_len = 0;
694 695
695 vis_server = atomic_read(&bat_priv->vis_mode); 696 vis_server = atomic_read(&bat_priv->vis_mode);
696 primary_if = batadv_primary_if_get_selected(bat_priv); 697 primary_if = batadv_primary_if_get_selected(bat_priv);
697 698
698 if (hard_iface == primary_if) 699 if (hard_iface == primary_if)
699 tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff, 700 tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
700 ogm_buff_len, 701 ogm_buff_len,
701 BATADV_OGM_HLEN); 702 BATADV_OGM_HLEN);
702 703
703 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff); 704 batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
705 batadv_ogm_packet->tvlv_len = htons(tvlv_len);
704 706
705 /* change sequence number to network order */ 707 /* change sequence number to network order */
706 seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno); 708 seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
@@ -1254,6 +1256,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
1254 goto out; 1256 goto out;
1255 } 1257 }
1256 1258
1259 batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node);
1260
1257 /* if sender is a direct neighbor the sender mac equals 1261 /* if sender is a direct neighbor the sender mac equals
1258 * originator mac 1262 * originator mac
1259 */ 1263 */
@@ -1350,9 +1354,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
1350 struct batadv_ogm_packet *batadv_ogm_packet; 1354 struct batadv_ogm_packet *batadv_ogm_packet;
1351 struct ethhdr *ethhdr; 1355 struct ethhdr *ethhdr;
1352 int buff_pos = 0, packet_len; 1356 int buff_pos = 0, packet_len;
1353 unsigned char *tt_buff, *packet_buff; 1357 unsigned char *tvlv_buff, *packet_buff;
1354 bool ret;
1355 uint8_t *packet_pos; 1358 uint8_t *packet_pos;
1359 bool ret;
1356 1360
1357 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); 1361 ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
1358 if (!ret) 1362 if (!ret)
@@ -1375,14 +1379,14 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
1375 1379
1376 /* unpack the aggregated packets and process them one by one */ 1380 /* unpack the aggregated packets and process them one by one */
1377 while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, 1381 while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
1378 batadv_ogm_packet->tt_num_changes)) { 1382 batadv_ogm_packet->tvlv_len)) {
1379 tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; 1383 tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
1380 1384
1381 batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, 1385 batadv_iv_ogm_process(ethhdr, batadv_ogm_packet,
1382 if_incoming); 1386 tvlv_buff, if_incoming);
1383 1387
1384 buff_pos += BATADV_OGM_HLEN; 1388 buff_pos += BATADV_OGM_HLEN;
1385 buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); 1389 buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
1386 1390
1387 packet_pos = packet_buff + buff_pos; 1391 packet_pos = packet_buff + buff_pos;
1388 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; 1392 batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 1356af660b5b..e2de68a5b0c6 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -36,6 +36,7 @@
36#include "gateway_client.h" 36#include "gateway_client.h"
37#include "bridge_loop_avoidance.h" 37#include "bridge_loop_avoidance.h"
38#include "distributed-arp-table.h" 38#include "distributed-arp-table.h"
39#include "unicast.h"
39#include "vis.h" 40#include "vis.h"
40#include "hash.h" 41#include "hash.h"
41#include "bat_algo.h" 42#include "bat_algo.h"
@@ -112,6 +113,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
112 spin_lock_init(&bat_priv->gw.list_lock); 113 spin_lock_init(&bat_priv->gw.list_lock);
113 spin_lock_init(&bat_priv->vis.hash_lock); 114 spin_lock_init(&bat_priv->vis.hash_lock);
114 spin_lock_init(&bat_priv->vis.list_lock); 115 spin_lock_init(&bat_priv->vis.list_lock);
116 spin_lock_init(&bat_priv->tvlv.container_list_lock);
117 spin_lock_init(&bat_priv->tvlv.handler_list_lock);
115 118
116 INIT_HLIST_HEAD(&bat_priv->forw_bat_list); 119 INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
117 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); 120 INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
@@ -119,6 +122,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
119 INIT_LIST_HEAD(&bat_priv->tt.changes_list); 122 INIT_LIST_HEAD(&bat_priv->tt.changes_list);
120 INIT_LIST_HEAD(&bat_priv->tt.req_list); 123 INIT_LIST_HEAD(&bat_priv->tt.req_list);
121 INIT_LIST_HEAD(&bat_priv->tt.roam_list); 124 INIT_LIST_HEAD(&bat_priv->tt.roam_list);
125 INIT_HLIST_HEAD(&bat_priv->tvlv.container_list);
126 INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list);
122 127
123 ret = batadv_originator_init(bat_priv); 128 ret = batadv_originator_init(bat_priv);
124 if (ret < 0) 129 if (ret < 0)
@@ -408,6 +413,8 @@ static void batadv_recv_handler_init(void)
408 batadv_rx_handler[BATADV_TT_QUERY] = batadv_recv_tt_query; 413 batadv_rx_handler[BATADV_TT_QUERY] = batadv_recv_tt_query;
409 /* Roaming advertisement */ 414 /* Roaming advertisement */
410 batadv_rx_handler[BATADV_ROAM_ADV] = batadv_recv_roam_adv; 415 batadv_rx_handler[BATADV_ROAM_ADV] = batadv_recv_roam_adv;
416 /* unicast tvlv packet */
417 batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
411} 418}
412 419
413int 420int
@@ -536,6 +543,574 @@ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
536 return htonl(crc); 543 return htonl(crc);
537} 544}
538 545
546/**
547 * batadv_tvlv_handler_free_ref - decrement the tvlv handler refcounter and
548 * possibly free it
549 * @tvlv_handler: the tvlv handler to free
550 */
551static void
552batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler)
553{
554 if (atomic_dec_and_test(&tvlv_handler->refcount))
555 kfree_rcu(tvlv_handler, rcu);
556}
557
558/**
559 * batadv_tvlv_handler_get - retrieve tvlv handler from the tvlv handler list
560 * based on the provided type and version (both need to match)
561 * @bat_priv: the bat priv with all the soft interface information
562 * @type: tvlv handler type to look for
563 * @version: tvlv handler version to look for
564 *
565 * Returns tvlv handler if found or NULL otherwise.
566 */
567static struct batadv_tvlv_handler
568*batadv_tvlv_handler_get(struct batadv_priv *bat_priv,
569 uint8_t type, uint8_t version)
570{
571 struct batadv_tvlv_handler *tvlv_handler_tmp, *tvlv_handler = NULL;
572
573 rcu_read_lock();
574 hlist_for_each_entry_rcu(tvlv_handler_tmp,
575 &bat_priv->tvlv.handler_list, list) {
576 if (tvlv_handler_tmp->type != type)
577 continue;
578
579 if (tvlv_handler_tmp->version != version)
580 continue;
581
582 if (!atomic_inc_not_zero(&tvlv_handler_tmp->refcount))
583 continue;
584
585 tvlv_handler = tvlv_handler_tmp;
586 break;
587 }
588 rcu_read_unlock();
589
590 return tvlv_handler;
591}
592
593/**
594 * batadv_tvlv_container_free_ref - decrement the tvlv container refcounter and
595 * possibly free it
596 * @tvlv_handler: the tvlv container to free
597 */
598static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv)
599{
600 if (atomic_dec_and_test(&tvlv->refcount))
601 kfree(tvlv);
602}
603
604/**
605 * batadv_tvlv_container_get - retrieve tvlv container from the tvlv container
606 * list based on the provided type and version (both need to match)
607 * @bat_priv: the bat priv with all the soft interface information
608 * @type: tvlv container type to look for
609 * @version: tvlv container version to look for
610 *
611 * Has to be called with the appropriate locks being acquired
612 * (tvlv.container_list_lock).
613 *
614 * Returns tvlv container if found or NULL otherwise.
615 */
616static struct batadv_tvlv_container
617*batadv_tvlv_container_get(struct batadv_priv *bat_priv,
618 uint8_t type, uint8_t version)
619{
620 struct batadv_tvlv_container *tvlv_tmp, *tvlv = NULL;
621
622 hlist_for_each_entry(tvlv_tmp, &bat_priv->tvlv.container_list, list) {
623 if (tvlv_tmp->tvlv_hdr.type != type)
624 continue;
625
626 if (tvlv_tmp->tvlv_hdr.version != version)
627 continue;
628
629 if (!atomic_inc_not_zero(&tvlv_tmp->refcount))
630 continue;
631
632 tvlv = tvlv_tmp;
633 break;
634 }
635
636 return tvlv;
637}
638
639/**
640 * batadv_tvlv_container_list_size - calculate the size of the tvlv container
641 * list entries
642 * @bat_priv: the bat priv with all the soft interface information
643 *
644 * Has to be called with the appropriate locks being acquired
645 * (tvlv.container_list_lock).
646 *
647 * Returns size of all currently registered tvlv containers in bytes.
648 */
649static uint16_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
650{
651 struct batadv_tvlv_container *tvlv;
652 uint16_t tvlv_len = 0;
653
654 hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
655 tvlv_len += sizeof(struct batadv_tvlv_hdr);
656 tvlv_len += ntohs(tvlv->tvlv_hdr.len);
657 }
658
659 return tvlv_len;
660}
661
662/**
663 * batadv_tvlv_container_remove - remove tvlv container from the tvlv container
664 * list
665 * @tvlv: the to be removed tvlv container
666 *
667 * Has to be called with the appropriate locks being acquired
668 * (tvlv.container_list_lock).
669 */
670static void batadv_tvlv_container_remove(struct batadv_tvlv_container *tvlv)
671{
672 if (!tvlv)
673 return;
674
675 hlist_del(&tvlv->list);
676
677 /* first call to decrement the counter, second call to free */
678 batadv_tvlv_container_free_ref(tvlv);
679 batadv_tvlv_container_free_ref(tvlv);
680}
681
682/**
683 * batadv_tvlv_container_unregister - unregister tvlv container based on the
684 * provided type and version (both need to match)
685 * @bat_priv: the bat priv with all the soft interface information
686 * @type: tvlv container type to unregister
687 * @version: tvlv container type to unregister
688 */
689void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
690 uint8_t type, uint8_t version)
691{
692 struct batadv_tvlv_container *tvlv;
693
694 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
695 tvlv = batadv_tvlv_container_get(bat_priv, type, version);
696 batadv_tvlv_container_remove(tvlv);
697 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
698}
699
700/**
701 * batadv_tvlv_container_register - register tvlv type, version and content
702 * to be propagated with each (primary interface) OGM
703 * @bat_priv: the bat priv with all the soft interface information
704 * @type: tvlv container type
705 * @version: tvlv container version
706 * @tvlv_value: tvlv container content
707 * @tvlv_value_len: tvlv container content length
708 *
709 * If a container of the same type and version was already registered the new
710 * content is going to replace the old one.
711 */
712void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
713 uint8_t type, uint8_t version,
714 void *tvlv_value, uint16_t tvlv_value_len)
715{
716 struct batadv_tvlv_container *tvlv_old, *tvlv_new;
717
718 if (!tvlv_value)
719 tvlv_value_len = 0;
720
721 tvlv_new = kzalloc(sizeof(*tvlv_new) + tvlv_value_len, GFP_ATOMIC);
722 if (!tvlv_new)
723 return;
724
725 tvlv_new->tvlv_hdr.version = version;
726 tvlv_new->tvlv_hdr.type = type;
727 tvlv_new->tvlv_hdr.len = htons(tvlv_value_len);
728
729 memcpy(tvlv_new + 1, tvlv_value, ntohs(tvlv_new->tvlv_hdr.len));
730 INIT_HLIST_NODE(&tvlv_new->list);
731 atomic_set(&tvlv_new->refcount, 1);
732
733 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
734 tvlv_old = batadv_tvlv_container_get(bat_priv, type, version);
735 batadv_tvlv_container_remove(tvlv_old);
736 hlist_add_head(&tvlv_new->list, &bat_priv->tvlv.container_list);
737 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
738}
739
740/**
741 * batadv_tvlv_realloc_packet_buff - reallocate packet buffer to accomodate
742 * requested packet size
743 * @packet_buff: packet buffer
744 * @packet_buff_len: packet buffer size
745 * @packet_min_len: requested packet minimum size
746 * @additional_packet_len: requested additional packet size on top of minimum
747 * size
748 *
749 * Returns true of the packet buffer could be changed to the requested size,
750 * false otherwise.
751 */
752static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
753 int *packet_buff_len,
754 int min_packet_len,
755 int additional_packet_len)
756{
757 unsigned char *new_buff;
758
759 new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC);
760
761 /* keep old buffer if kmalloc should fail */
762 if (new_buff) {
763 memcpy(new_buff, *packet_buff, min_packet_len);
764 kfree(*packet_buff);
765 *packet_buff = new_buff;
766 *packet_buff_len = min_packet_len + additional_packet_len;
767 return true;
768 }
769
770 return false;
771}
772
773/**
774 * batadv_tvlv_container_ogm_append - append tvlv container content to given
775 * OGM packet buffer
776 * @bat_priv: the bat priv with all the soft interface information
777 * @packet_buff: ogm packet buffer
778 * @packet_buff_len: ogm packet buffer size including ogm header and tvlv
779 * content
780 * @packet_min_len: ogm header size to be preserved for the OGM itself
781 *
782 * The ogm packet might be enlarged or shrunk depending on the current size
783 * and the size of the to-be-appended tvlv containers.
784 *
785 * Returns size of all appended tvlv containers in bytes.
786 */
787uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
788 unsigned char **packet_buff,
789 int *packet_buff_len,
790 int packet_min_len)
791{
792 struct batadv_tvlv_container *tvlv;
793 struct batadv_tvlv_hdr *tvlv_hdr;
794 uint16_t tvlv_value_len;
795 void *tvlv_value;
796 bool ret;
797
798 spin_lock_bh(&bat_priv->tvlv.container_list_lock);
799 tvlv_value_len = batadv_tvlv_container_list_size(bat_priv);
800
801 ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len,
802 packet_min_len, tvlv_value_len);
803
804 if (!ret)
805 goto end;
806
807 if (!tvlv_value_len)
808 goto end;
809
810 tvlv_value = (*packet_buff) + packet_min_len;
811
812 hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
813 tvlv_hdr = tvlv_value;
814 tvlv_hdr->type = tvlv->tvlv_hdr.type;
815 tvlv_hdr->version = tvlv->tvlv_hdr.version;
816 tvlv_hdr->len = tvlv->tvlv_hdr.len;
817 tvlv_value = tvlv_hdr + 1;
818 memcpy(tvlv_value, tvlv + 1, ntohs(tvlv->tvlv_hdr.len));
819 tvlv_value = (uint8_t *)tvlv_value + ntohs(tvlv->tvlv_hdr.len);
820 }
821
822end:
823 spin_unlock_bh(&bat_priv->tvlv.container_list_lock);
824 return tvlv_value_len;
825}
826
827/**
828 * batadv_tvlv_call_handler - parse the given tvlv buffer to call the
829 * appropriate handlers
830 * @bat_priv: the bat priv with all the soft interface information
831 * @tvlv_handler: tvlv callback function handling the tvlv content
832 * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet
833 * @orig_node: orig node emitting the ogm packet
834 * @src: source mac address of the unicast packet
835 * @dst: destination mac address of the unicast packet
836 * @tvlv_value: tvlv content
837 * @tvlv_value_len: tvlv content length
838 *
839 * Returns success if handler was not found or the return value of the handler
840 * callback.
841 */
842static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,
843 struct batadv_tvlv_handler *tvlv_handler,
844 bool ogm_source,
845 struct batadv_orig_node *orig_node,
846 uint8_t *src, uint8_t *dst,
847 void *tvlv_value, uint16_t tvlv_value_len)
848{
849 if (!tvlv_handler)
850 return NET_RX_SUCCESS;
851
852 if (ogm_source) {
853 if (!tvlv_handler->ogm_handler)
854 return NET_RX_SUCCESS;
855
856 if (!orig_node)
857 return NET_RX_SUCCESS;
858
859 tvlv_handler->ogm_handler(bat_priv, orig_node,
860 BATADV_NO_FLAGS,
861 tvlv_value, tvlv_value_len);
862 tvlv_handler->flags |= BATADV_TVLV_HANDLER_OGM_CALLED;
863 } else {
864 if (!src)
865 return NET_RX_SUCCESS;
866
867 if (!dst)
868 return NET_RX_SUCCESS;
869
870 if (!tvlv_handler->unicast_handler)
871 return NET_RX_SUCCESS;
872
873 return tvlv_handler->unicast_handler(bat_priv, src,
874 dst, tvlv_value,
875 tvlv_value_len);
876 }
877
878 return NET_RX_SUCCESS;
879}
880
881/**
882 * batadv_tvlv_containers_process - parse the given tvlv buffer to call the
883 * appropriate handlers
884 * @bat_priv: the bat priv with all the soft interface information
885 * @ogm_source: flag indicating wether the tvlv is an ogm or a unicast packet
886 * @orig_node: orig node emitting the ogm packet
887 * @src: source mac address of the unicast packet
888 * @dst: destination mac address of the unicast packet
889 * @tvlv_value: tvlv content
890 * @tvlv_value_len: tvlv content length
891 *
892 * Returns success when processing an OGM or the return value of all called
893 * handler callbacks.
894 */
895int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
896 bool ogm_source,
897 struct batadv_orig_node *orig_node,
898 uint8_t *src, uint8_t *dst,
899 void *tvlv_value, uint16_t tvlv_value_len)
900{
901 struct batadv_tvlv_handler *tvlv_handler;
902 struct batadv_tvlv_hdr *tvlv_hdr;
903 uint16_t tvlv_value_cont_len;
904 uint8_t cifnotfound = BATADV_TVLV_HANDLER_OGM_CIFNOTFND;
905 int ret = NET_RX_SUCCESS;
906
907 while (tvlv_value_len >= sizeof(*tvlv_hdr)) {
908 tvlv_hdr = tvlv_value;
909 tvlv_value_cont_len = ntohs(tvlv_hdr->len);
910 tvlv_value = tvlv_hdr + 1;
911 tvlv_value_len -= sizeof(*tvlv_hdr);
912
913 if (tvlv_value_cont_len > tvlv_value_len)
914 break;
915
916 tvlv_handler = batadv_tvlv_handler_get(bat_priv,
917 tvlv_hdr->type,
918 tvlv_hdr->version);
919
920 ret |= batadv_tvlv_call_handler(bat_priv, tvlv_handler,
921 ogm_source, orig_node,
922 src, dst, tvlv_value,
923 tvlv_value_cont_len);
924 if (tvlv_handler)
925 batadv_tvlv_handler_free_ref(tvlv_handler);
926 tvlv_value = (uint8_t *)tvlv_value + tvlv_value_cont_len;
927 tvlv_value_len -= tvlv_value_cont_len;
928 }
929
930 if (!ogm_source)
931 return ret;
932
933 rcu_read_lock();
934 hlist_for_each_entry_rcu(tvlv_handler,
935 &bat_priv->tvlv.handler_list, list) {
936 if ((tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) &&
937 !(tvlv_handler->flags & BATADV_TVLV_HANDLER_OGM_CALLED))
938 tvlv_handler->ogm_handler(bat_priv, orig_node,
939 cifnotfound, NULL, 0);
940
941 tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED;
942 }
943 rcu_read_unlock();
944
945 return NET_RX_SUCCESS;
946}
947
948/**
949 * batadv_tvlv_ogm_receive - process an incoming ogm and call the appropriate
950 * handlers
951 * @bat_priv: the bat priv with all the soft interface information
952 * @batadv_ogm_packet: ogm packet containing the tvlv containers
953 * @orig_node: orig node emitting the ogm packet
954 */
955void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
956 struct batadv_ogm_packet *batadv_ogm_packet,
957 struct batadv_orig_node *orig_node)
958{
959 void *tvlv_value;
960 uint16_t tvlv_value_len;
961
962 if (!batadv_ogm_packet)
963 return;
964
965 tvlv_value_len = ntohs(batadv_ogm_packet->tvlv_len);
966 if (!tvlv_value_len)
967 return;
968
969 tvlv_value = batadv_ogm_packet + 1;
970
971 batadv_tvlv_containers_process(bat_priv, true, orig_node, NULL, NULL,
972 tvlv_value, tvlv_value_len);
973}
974
975/**
976 * batadv_tvlv_handler_register - register tvlv handler based on the provided
977 * type and version (both need to match) for ogm tvlv payload and/or unicast
978 * payload
979 * @bat_priv: the bat priv with all the soft interface information
980 * @optr: ogm tvlv handler callback function. This function receives the orig
981 * node, flags and the tvlv content as argument to process.
982 * @uptr: unicast tvlv handler callback function. This function receives the
983 * source & destination of the unicast packet as well as the tvlv content
984 * to process.
985 * @type: tvlv handler type to be registered
986 * @version: tvlv handler version to be registered
987 * @flags: flags to enable or disable TVLV API behavior
988 */
989void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
990 void (*optr)(struct batadv_priv *bat_priv,
991 struct batadv_orig_node *orig,
992 uint8_t flags,
993 void *tvlv_value,
994 uint16_t tvlv_value_len),
995 int (*uptr)(struct batadv_priv *bat_priv,
996 uint8_t *src, uint8_t *dst,
997 void *tvlv_value,
998 uint16_t tvlv_value_len),
999 uint8_t type, uint8_t version, uint8_t flags)
1000{
1001 struct batadv_tvlv_handler *tvlv_handler;
1002
1003 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
1004 if (tvlv_handler) {
1005 batadv_tvlv_handler_free_ref(tvlv_handler);
1006 return;
1007 }
1008
1009 tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC);
1010 if (!tvlv_handler)
1011 return;
1012
1013 tvlv_handler->ogm_handler = optr;
1014 tvlv_handler->unicast_handler = uptr;
1015 tvlv_handler->type = type;
1016 tvlv_handler->version = version;
1017 tvlv_handler->flags = flags;
1018 atomic_set(&tvlv_handler->refcount, 1);
1019 INIT_HLIST_NODE(&tvlv_handler->list);
1020
1021 spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
1022 hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
1023 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
1024}
1025
1026/**
1027 * batadv_tvlv_handler_unregister - unregister tvlv handler based on the
1028 * provided type and version (both need to match)
1029 * @bat_priv: the bat priv with all the soft interface information
1030 * @type: tvlv handler type to be unregistered
1031 * @version: tvlv handler version to be unregistered
1032 */
1033void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
1034 uint8_t type, uint8_t version)
1035{
1036 struct batadv_tvlv_handler *tvlv_handler;
1037
1038 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
1039 if (!tvlv_handler)
1040 return;
1041
1042 batadv_tvlv_handler_free_ref(tvlv_handler);
1043 spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
1044 hlist_del_rcu(&tvlv_handler->list);
1045 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
1046 batadv_tvlv_handler_free_ref(tvlv_handler);
1047}
1048
1049/**
1050 * batadv_tvlv_unicast_send - send a unicast packet with tvlv payload to the
1051 * specified host
1052 * @bat_priv: the bat priv with all the soft interface information
1053 * @src: source mac address of the unicast packet
1054 * @dst: destination mac address of the unicast packet
1055 * @type: tvlv type
1056 * @version: tvlv version
1057 * @tvlv_value: tvlv content
1058 * @tvlv_value_len: tvlv content length
1059 */
1060void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
1061 uint8_t *dst, uint8_t type, uint8_t version,
1062 void *tvlv_value, uint16_t tvlv_value_len)
1063{
1064 struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
1065 struct batadv_tvlv_hdr *tvlv_hdr;
1066 struct batadv_orig_node *orig_node;
1067 struct sk_buff *skb = NULL;
1068 unsigned char *tvlv_buff;
1069 unsigned int tvlv_len;
1070 ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
1071 bool ret = false;
1072
1073 orig_node = batadv_orig_hash_find(bat_priv, dst);
1074 if (!orig_node)
1075 goto out;
1076
1077 tvlv_len = sizeof(*tvlv_hdr) + tvlv_value_len;
1078
1079 skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + hdr_len + tvlv_len);
1080 if (!skb)
1081 goto out;
1082
1083 skb->priority = TC_PRIO_CONTROL;
1084 skb_reserve(skb, ETH_HLEN);
1085 tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
1086 unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
1087 unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
1088 unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
1089 unicast_tvlv_packet->header.ttl = BATADV_TTL;
1090 unicast_tvlv_packet->reserved = 0;
1091 unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
1092 unicast_tvlv_packet->align = 0;
1093 memcpy(unicast_tvlv_packet->src, src, ETH_ALEN);
1094 memcpy(unicast_tvlv_packet->dst, dst, ETH_ALEN);
1095
1096 tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1);
1097 tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff;
1098 tvlv_hdr->version = version;
1099 tvlv_hdr->type = type;
1100 tvlv_hdr->len = htons(tvlv_value_len);
1101 tvlv_buff += sizeof(*tvlv_hdr);
1102 memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
1103
1104 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
1105 ret = true;
1106
1107out:
1108 if (skb && !ret)
1109 kfree_skb(skb);
1110 if (orig_node)
1111 batadv_orig_node_free_ref(orig_node);
1112}
1113
539static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) 1114static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
540{ 1115{
541 struct batadv_algo_ops *bat_algo_ops; 1116 struct batadv_algo_ops *bat_algo_ops;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 24675523930f..397722fb509b 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -326,4 +326,39 @@ static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv,
326 */ 326 */
327#define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0])) 327#define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0]))
328 328
329void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
330 uint8_t type, uint8_t version,
331 void *tvlv_value, uint16_t tvlv_value_len);
332uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
333 unsigned char **packet_buff,
334 int *packet_buff_len,
335 int packet_min_len);
336void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
337 struct batadv_ogm_packet *batadv_ogm_packet,
338 struct batadv_orig_node *orig_node);
339void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
340 uint8_t type, uint8_t version);
341
342void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
343 void (*optr)(struct batadv_priv *bat_priv,
344 struct batadv_orig_node *orig,
345 uint8_t flags,
346 void *tvlv_value,
347 uint16_t tvlv_value_len),
348 int (*uptr)(struct batadv_priv *bat_priv,
349 uint8_t *src, uint8_t *dst,
350 void *tvlv_value,
351 uint16_t tvlv_value_len),
352 uint8_t type, uint8_t version, uint8_t flags);
353void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
354 uint8_t type, uint8_t version);
355int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
356 bool ogm_source,
357 struct batadv_orig_node *orig_node,
358 uint8_t *src, uint8_t *dst,
359 void *tvlv_buff, uint16_t tvlv_buff_len);
360void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
361 uint8_t *dst, uint8_t type, uint8_t version,
362 void *tvlv_value, uint16_t tvlv_value_len);
363
329#endif /* _NET_BATMAN_ADV_MAIN_H_ */ 364#endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 11a22c8c3cbb..b5c21c418a5f 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -20,6 +20,10 @@
20#ifndef _NET_BATMAN_ADV_PACKET_H_ 20#ifndef _NET_BATMAN_ADV_PACKET_H_
21#define _NET_BATMAN_ADV_PACKET_H_ 21#define _NET_BATMAN_ADV_PACKET_H_
22 22
23/**
24 * enum batadv_packettype - types for batman-adv encapsulated packets
25 * @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers
26 */
23enum batadv_packettype { 27enum batadv_packettype {
24 BATADV_IV_OGM = 0x01, 28 BATADV_IV_OGM = 0x01,
25 BATADV_ICMP = 0x02, 29 BATADV_ICMP = 0x02,
@@ -31,6 +35,7 @@ enum batadv_packettype {
31 BATADV_ROAM_ADV = 0x08, 35 BATADV_ROAM_ADV = 0x08,
32 BATADV_UNICAST_4ADDR = 0x09, 36 BATADV_UNICAST_4ADDR = 0x09,
33 BATADV_CODED = 0x0a, 37 BATADV_CODED = 0x0a,
38 BATADV_UNICAST_TVLV = 0x0b,
34}; 39};
35 40
36/** 41/**
@@ -131,6 +136,11 @@ struct batadv_header {
131 */ 136 */
132}; 137};
133 138
139/**
140 * struct batadv_ogm_packet - ogm (routing protocol) packet
141 * @header: common batman packet header
142 * @tvlv_len: length of tvlv data following the ogm header
143 */
134struct batadv_ogm_packet { 144struct batadv_ogm_packet {
135 struct batadv_header header; 145 struct batadv_header header;
136 uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ 146 uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
@@ -142,6 +152,7 @@ struct batadv_ogm_packet {
142 uint8_t tt_num_changes; 152 uint8_t tt_num_changes;
143 uint8_t ttvn; /* translation table version number */ 153 uint8_t ttvn; /* translation table version number */
144 __be16 tt_crc; 154 __be16 tt_crc;
155 __be16 tvlv_len;
145} __packed; 156} __packed;
146 157
147#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) 158#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
@@ -311,4 +322,34 @@ struct batadv_coded_packet {
311 __be16 coded_len; 322 __be16 coded_len;
312}; 323};
313 324
325/**
326 * struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
327 * @header: common batman packet header
328 * @reserved: reserved field (for packet alignment)
329 * @src: address of the source
330 * @dst: address of the destination
331 * @tvlv_len: length of tvlv data following the unicast tvlv header
332 * @align: 2 bytes to align the header to a 4 byte boundry
333 */
334struct batadv_unicast_tvlv_packet {
335 struct batadv_header header;
336 uint8_t reserved;
337 uint8_t dst[ETH_ALEN];
338 uint8_t src[ETH_ALEN];
339 __be16 tvlv_len;
340 uint16_t align;
341};
342
343/**
344 * struct batadv_tvlv_hdr - base tvlv header struct
345 * @type: tvlv container type (see batadv_tvlv_type)
346 * @version: tvlv container version
347 * @len: tvlv container length
348 */
349struct batadv_tvlv_hdr {
350 uint8_t type;
351 uint8_t version;
352 __be16 len;
353};
354
314#endif /* _NET_BATMAN_ADV_PACKET_H_ */ 355#endif /* _NET_BATMAN_ADV_PACKET_H_ */
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 0439395d7ba5..9640656d4e51 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -1139,6 +1139,54 @@ rx_success:
1139 return batadv_route_unicast_packet(skb, recv_if); 1139 return batadv_route_unicast_packet(skb, recv_if);
1140} 1140}
1141 1141
1142/**
1143 * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
1144 * @skb: unicast tvlv packet to process
1145 * @recv_if: pointer to interface this packet was received on
1146 * @dst_addr: the payload destination
1147 *
1148 * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
1149 * otherwise.
1150 */
1151int batadv_recv_unicast_tvlv(struct sk_buff *skb,
1152 struct batadv_hard_iface *recv_if)
1153{
1154 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1155 struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
1156 unsigned char *tvlv_buff;
1157 uint16_t tvlv_buff_len;
1158 int hdr_size = sizeof(*unicast_tvlv_packet);
1159 int ret = NET_RX_DROP;
1160
1161 if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
1162 return NET_RX_DROP;
1163
1164 /* the header is likely to be modified while forwarding */
1165 if (skb_cow(skb, hdr_size) < 0)
1166 return NET_RX_DROP;
1167
1168 /* packet needs to be linearized to access the tvlv content */
1169 if (skb_linearize(skb) < 0)
1170 return NET_RX_DROP;
1171
1172 unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data;
1173
1174 tvlv_buff = (unsigned char *)(skb->data + hdr_size);
1175 tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len);
1176
1177 if (tvlv_buff_len > skb->len - hdr_size)
1178 return NET_RX_DROP;
1179
1180 ret = batadv_tvlv_containers_process(bat_priv, false, NULL,
1181 unicast_tvlv_packet->src,
1182 unicast_tvlv_packet->dst,
1183 tvlv_buff, tvlv_buff_len);
1184
1185 if (ret != NET_RX_SUCCESS)
1186 ret = batadv_route_unicast_packet(skb, recv_if);
1187
1188 return ret;
1189}
1142 1190
1143int batadv_recv_bcast_packet(struct sk_buff *skb, 1191int batadv_recv_bcast_packet(struct sk_buff *skb,
1144 struct batadv_hard_iface *recv_if) 1192 struct batadv_hard_iface *recv_if)
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index 72a29bde2010..0a7983b25395 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -40,6 +40,8 @@ int batadv_recv_tt_query(struct sk_buff *skb,
40 struct batadv_hard_iface *recv_if); 40 struct batadv_hard_iface *recv_if);
41int batadv_recv_roam_adv(struct sk_buff *skb, 41int batadv_recv_roam_adv(struct sk_buff *skb,
42 struct batadv_hard_iface *recv_if); 42 struct batadv_hard_iface *recv_if);
43int batadv_recv_unicast_tvlv(struct sk_buff *skb,
44 struct batadv_hard_iface *recv_if);
43struct batadv_neigh_node * 45struct batadv_neigh_node *
44batadv_find_router(struct batadv_priv *bat_priv, 46batadv_find_router(struct batadv_priv *bat_priv,
45 struct batadv_orig_node *orig_node, 47 struct batadv_orig_node *orig_node,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index b2c94e139319..4bdea16bc70c 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -430,6 +430,20 @@ struct batadv_priv_gw {
430}; 430};
431 431
432/** 432/**
433 * struct batadv_priv_tvlv - per mesh interface tvlv data
434 * @container_list: list of registered tvlv containers to be sent with each OGM
435 * @handler_list: list of the various tvlv content handlers
436 * @container_list_lock: protects tvlv container list access
437 * @handler_list_lock: protects handler list access
438 */
439struct batadv_priv_tvlv {
440 struct hlist_head container_list;
441 struct hlist_head handler_list;
442 spinlock_t container_list_lock; /* protects container_list */
443 spinlock_t handler_list_lock; /* protects handler_list */
444};
445
446/**
433 * struct batadv_priv_vis - per mesh interface vis data 447 * struct batadv_priv_vis - per mesh interface vis data
434 * @send_list: list of batadv_vis_info packets to sent 448 * @send_list: list of batadv_vis_info packets to sent
435 * @hash: hash table containing vis data from other nodes in the network 449 * @hash: hash table containing vis data from other nodes in the network
@@ -531,6 +545,7 @@ struct batadv_priv_nc {
531 * @debug_log: holding debug logging relevant data 545 * @debug_log: holding debug logging relevant data
532 * @gw: gateway data 546 * @gw: gateway data
533 * @tt: translation table data 547 * @tt: translation table data
548 * @tvlv: type-version-length-value data
534 * @vis: vis data 549 * @vis: vis data
535 * @dat: distributed arp table data 550 * @dat: distributed arp table data
536 * @network_coding: bool indicating whether network coding is enabled 551 * @network_coding: bool indicating whether network coding is enabled
@@ -583,6 +598,7 @@ struct batadv_priv {
583#endif 598#endif
584 struct batadv_priv_gw gw; 599 struct batadv_priv_gw gw;
585 struct batadv_priv_tt tt; 600 struct batadv_priv_tt tt;
601 struct batadv_priv_tvlv tvlv;
586 struct batadv_priv_vis vis; 602 struct batadv_priv_vis vis;
587#ifdef CONFIG_BATMAN_ADV_DAT 603#ifdef CONFIG_BATMAN_ADV_DAT
588 struct batadv_priv_dat dat; 604 struct batadv_priv_dat dat;
@@ -992,4 +1008,60 @@ struct batadv_dat_candidate {
992 struct batadv_orig_node *orig_node; 1008 struct batadv_orig_node *orig_node;
993}; 1009};
994 1010
1011/**
1012 * struct batadv_tvlv_container - container for tvlv appended to OGMs
1013 * @list: hlist node for batadv_priv_tvlv::container_list
1014 * @tvlv_hdr: tvlv header information needed to construct the tvlv
1015 * @value_len: length of the buffer following this struct which contains
1016 * the actual tvlv payload
1017 * @refcount: number of contexts the object is used
1018 */
1019struct batadv_tvlv_container {
1020 struct hlist_node list;
1021 struct batadv_tvlv_hdr tvlv_hdr;
1022 atomic_t refcount;
1023};
1024
1025/**
1026 * struct batadv_tvlv_handler - handler for specific tvlv type and version
1027 * @list: hlist node for batadv_priv_tvlv::handler_list
1028 * @ogm_handler: handler callback which is given the tvlv payload to process on
1029 * incoming OGM packets
1030 * @unicast_handler: handler callback which is given the tvlv payload to process
1031 * on incoming unicast tvlv packets
1032 * @type: tvlv type this handler feels responsible for
1033 * @version: tvlv version this handler feels responsible for
1034 * @flags: tvlv handler flags
1035 * @refcount: number of contexts the object is used
1036 * @rcu: struct used for freeing in an RCU-safe manner
1037 */
1038struct batadv_tvlv_handler {
1039 struct hlist_node list;
1040 void (*ogm_handler)(struct batadv_priv *bat_priv,
1041 struct batadv_orig_node *orig,
1042 uint8_t flags,
1043 void *tvlv_value, uint16_t tvlv_value_len);
1044 int (*unicast_handler)(struct batadv_priv *bat_priv,
1045 uint8_t *src, uint8_t *dst,
1046 void *tvlv_value, uint16_t tvlv_value_len);
1047 uint8_t type;
1048 uint8_t version;
1049 uint8_t flags;
1050 atomic_t refcount;
1051 struct rcu_head rcu;
1052};
1053
1054/**
1055 * enum batadv_tvlv_handler_flags - tvlv handler flags definitions
1056 * @BATADV_TVLV_HANDLER_OGM_CIFNOTFND: tvlv ogm processing function will call
1057 * this handler even if its type was not found (with no data)
1058 * @BATADV_TVLV_HANDLER_OGM_CALLED: interval tvlv handling flag - the API marks
1059 * a handler as being called, so it won't be called if the
1060 * BATADV_TVLV_HANDLER_OGM_CIFNOTFND flag was set
1061 */
1062enum batadv_tvlv_handler_flags {
1063 BATADV_TVLV_HANDLER_OGM_CIFNOTFND = BIT(1),
1064 BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2),
1065};
1066
995#endif /* _NET_BATMAN_ADV_TYPES_H_ */ 1067#endif /* _NET_BATMAN_ADV_TYPES_H_ */