aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/main.c
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 /net/batman-adv/main.c
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>
Diffstat (limited to 'net/batman-adv/main.c')
-rw-r--r--net/batman-adv/main.c575
1 files changed, 575 insertions, 0 deletions
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;