Commit 29b67c39 authored by David S. Miller's avatar David S. Miller

Merge tag 'batman-adv-for-davem' of git://git.open-mesh.org/linux-merge

Included changes:
- update emails for A. Quartulli and M. Lindner in MAINTAINERS
- switch to the next on-the-wire protocol version
- introduce the T(ype) V(ersion) L(ength) V(alue) framework
- adjust the existing components to make them use the new TVLV code
- make the TT component use CRC32 instead of CRC16
- totally remove the VIS functionality (has been moved to userspace)
- reorder packet types and flags
- add static checks on packet format
- remove __packed from batadv_ogm_packet
parents 58308451 18c68d59
...@@ -88,14 +88,3 @@ Contact: Marek Lindner <lindner_marek@yahoo.de> ...@@ -88,14 +88,3 @@ Contact: Marek Lindner <lindner_marek@yahoo.de>
Description: Description:
Defines the routing procotol this mesh instance Defines the routing procotol this mesh instance
uses to find the optimal paths through the mesh. uses to find the optimal paths through the mesh.
What: /sys/class/net/<mesh_iface>/mesh/vis_mode
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Each batman node only maintains information about its
own local neighborhood, therefore generating graphs
showing the topology of the entire mesh is not easily
feasible without having a central instance to collect
the local topologies from all nodes. This file allows
to activate the collecting (server) mode.
...@@ -69,8 +69,7 @@ folder: ...@@ -69,8 +69,7 @@ folder:
# aggregated_ogms gw_bandwidth log_level # aggregated_ogms gw_bandwidth log_level
# ap_isolation gw_mode orig_interval # ap_isolation gw_mode orig_interval
# bonding gw_sel_class routing_algo # bonding gw_sel_class routing_algo
# bridge_loop_avoidance hop_penalty vis_mode # bridge_loop_avoidance hop_penalty fragmentation
# fragmentation
There is a special folder for debugging information: There is a special folder for debugging information:
...@@ -78,7 +77,7 @@ There is a special folder for debugging information: ...@@ -78,7 +77,7 @@ There is a special folder for debugging information:
# ls /sys/kernel/debug/batman_adv/bat0/ # ls /sys/kernel/debug/batman_adv/bat0/
# bla_backbone_table log transtable_global # bla_backbone_table log transtable_global
# bla_claim_table originators transtable_local # bla_claim_table originators transtable_local
# gateways socket vis_data # gateways socket
Some of the files contain all sort of status information regard- Some of the files contain all sort of status information regard-
ing the mesh network. For example, you can view the table of ing the mesh network. For example, you can view the table of
...@@ -127,51 +126,6 @@ ously assigned to interfaces now used by batman advanced, e.g. ...@@ -127,51 +126,6 @@ ously assigned to interfaces now used by batman advanced, e.g.
# ifconfig eth0 0.0.0.0 # ifconfig eth0 0.0.0.0
VISUALIZATION
-------------
If you want topology visualization, at least one mesh node must
be configured as VIS-server:
# echo "server" > /sys/class/net/bat0/mesh/vis_mode
Each node is either configured as "server" or as "client" (de-
fault: "client"). Clients send their topology data to the server
next to them, and server synchronize with other servers. If there
is no server configured (default) within the mesh, no topology
information will be transmitted. With these "synchronizing
servers", there can be 1 or more vis servers sharing the same (or
at least very similar) data.
When configured as server, you can get a topology snapshot of
your mesh:
# cat /sys/kernel/debug/batman_adv/bat0/vis_data
This raw output is intended to be easily parsable and convertable
with other tools. Have a look at the batctl README if you want a
vis output in dot or json format for instance and how those out-
puts could then be visualised in an image.
The raw format consists of comma separated values per entry where
each entry is giving information about a certain source inter-
face. Each entry can/has to have the following values:
-> "mac" - mac address of an originator's source interface
(each line begins with it)
-> "TQ mac value" - src mac's link quality towards mac address
of a neighbor originator's interface which
is being used for routing
-> "TT mac" - TT announced by source mac
-> "PRIMARY" - this is a primary interface
-> "SEC mac" - secondary mac address of source
(requires preceding PRIMARY)
The TQ value has a range from 4 to 255 with 255 being the best.
The TT entries are showing which hosts are connected to the mesh
via bat0 or being bridged into the mesh network. The PRIMARY/SEC
values are only applied on primary interfaces
LOGGING/DEBUGGING LOGGING/DEBUGGING
----------------- -----------------
......
...@@ -1652,9 +1652,9 @@ F: drivers/video/backlight/ ...@@ -1652,9 +1652,9 @@ F: drivers/video/backlight/
F: include/linux/backlight.h F: include/linux/backlight.h
BATMAN ADVANCED BATMAN ADVANCED
M: Marek Lindner <lindner_marek@yahoo.de> M: Marek Lindner <mareklindner@neomailbox.ch>
M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
M: Antonio Quartulli <ordex@autistici.org> M: Antonio Quartulli <antonio@meshcoding.com>
L: b.a.t.m.a.n@lists.open-mesh.org L: b.a.t.m.a.n@lists.open-mesh.org
W: http://www.open-mesh.org/ W: http://www.open-mesh.org/
S: Maintained S: Maintained
......
...@@ -38,4 +38,3 @@ batman-adv-y += soft-interface.o ...@@ -38,4 +38,3 @@ batman-adv-y += soft-interface.o
batman-adv-y += sysfs.o batman-adv-y += sysfs.o
batman-adv-y += translation-table.o batman-adv-y += translation-table.o
batman-adv-y += unicast.o batman-adv-y += unicast.o
batman-adv-y += vis.o
...@@ -135,9 +135,8 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface) ...@@ -135,9 +135,8 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION; batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
batadv_ogm_packet->header.ttl = 2; batadv_ogm_packet->header.ttl = 2;
batadv_ogm_packet->flags = BATADV_NO_FLAGS; batadv_ogm_packet->flags = BATADV_NO_FLAGS;
batadv_ogm_packet->reserved = 0;
batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE; batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
batadv_ogm_packet->tt_num_changes = 0;
batadv_ogm_packet->ttvn = 0;
res = 0; res = 0;
...@@ -207,12 +206,12 @@ static uint8_t batadv_hop_penalty(uint8_t tq, ...@@ -207,12 +206,12 @@ static uint8_t batadv_hop_penalty(uint8_t tq,
/* is there another aggregated packet here? */ /* is there another aggregated packet here? */
static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, static int batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
int tt_num_changes) __be16 tvlv_len)
{ {
int next_buff_pos = 0; int next_buff_pos = 0;
next_buff_pos += buff_pos + BATADV_OGM_HLEN; next_buff_pos += buff_pos + BATADV_OGM_HLEN;
next_buff_pos += batadv_tt_len(tt_num_changes); next_buff_pos += ntohs(tvlv_len);
return (next_buff_pos <= packet_len) && return (next_buff_pos <= packet_len) &&
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
...@@ -240,7 +239,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, ...@@ -240,7 +239,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
/* adjust all flags and log packets */ /* adjust all flags and log packets */
while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
batadv_ogm_packet->tt_num_changes)) { batadv_ogm_packet->tvlv_len)) {
/* we might have aggregated direct link packets with an /* we might have aggregated direct link packets with an
* ordinary base packet * ordinary base packet
*/ */
...@@ -256,18 +255,18 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, ...@@ -256,18 +255,18 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
fwd_str = "Sending own"; fwd_str = "Sending own";
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n", "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s) on interface %s [%pM]\n",
fwd_str, (packet_num > 0 ? "aggregated " : ""), fwd_str, (packet_num > 0 ? "aggregated " : ""),
batadv_ogm_packet->orig, batadv_ogm_packet->orig,
ntohl(batadv_ogm_packet->seqno), ntohl(batadv_ogm_packet->seqno),
batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl, batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl,
(batadv_ogm_packet->flags & BATADV_DIRECTLINK ? (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
"on" : "off"), "on" : "off"),
batadv_ogm_packet->ttvn, hard_iface->net_dev->name, hard_iface->net_dev->name,
hard_iface->net_dev->dev_addr); hard_iface->net_dev->dev_addr);
buff_pos += BATADV_OGM_HLEN; buff_pos += BATADV_OGM_HLEN;
buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
packet_num++; packet_num++;
packet_pos = forw_packet->skb->data + buff_pos; packet_pos = forw_packet->skb->data + buff_pos;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
...@@ -601,7 +600,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, ...@@ -601,7 +600,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
struct batadv_hard_iface *if_incoming) struct batadv_hard_iface *if_incoming)
{ {
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
uint8_t tt_num_changes; uint16_t tvlv_len;
if (batadv_ogm_packet->header.ttl <= 1) { if (batadv_ogm_packet->header.ttl <= 1) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n"); batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
...@@ -621,7 +620,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, ...@@ -621,7 +620,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
return; return;
} }
tt_num_changes = batadv_ogm_packet->tt_num_changes; tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
batadv_ogm_packet->header.ttl--; batadv_ogm_packet->header.ttl--;
memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
...@@ -642,7 +641,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, ...@@ -642,7 +641,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK; batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK;
batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet, batadv_iv_ogm_queue_add(bat_priv, (unsigned char *)batadv_ogm_packet,
BATADV_OGM_HLEN + batadv_tt_len(tt_num_changes), BATADV_OGM_HLEN + tvlv_len,
if_incoming, 0, batadv_iv_ogm_fwd_send_time()); if_incoming, 0, batadv_iv_ogm_fwd_send_time());
} }
...@@ -688,43 +687,29 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) ...@@ -688,43 +687,29 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
struct batadv_ogm_packet *batadv_ogm_packet; struct batadv_ogm_packet *batadv_ogm_packet;
struct batadv_hard_iface *primary_if; struct batadv_hard_iface *primary_if;
int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len; int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
int vis_server, tt_num_changes = 0;
uint32_t seqno; uint32_t seqno;
uint8_t bandwidth; uint16_t tvlv_len = 0;
vis_server = atomic_read(&bat_priv->vis_mode);
primary_if = batadv_primary_if_get_selected(bat_priv); primary_if = batadv_primary_if_get_selected(bat_priv);
if (hard_iface == primary_if) if (hard_iface == primary_if) {
tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff, /* tt changes have to be committed before the tvlv data is
* appended as it may alter the tt tvlv container
*/
batadv_tt_local_commit_changes(bat_priv);
tvlv_len = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
ogm_buff_len, ogm_buff_len,
BATADV_OGM_HLEN); BATADV_OGM_HLEN);
}
batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff); batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
batadv_ogm_packet->tvlv_len = htons(tvlv_len);
/* change sequence number to network order */ /* change sequence number to network order */
seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno); seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
batadv_ogm_packet->seqno = htonl(seqno); batadv_ogm_packet->seqno = htonl(seqno);
atomic_inc(&hard_iface->bat_iv.ogm_seqno); atomic_inc(&hard_iface->bat_iv.ogm_seqno);
batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
if (tt_num_changes >= 0)
batadv_ogm_packet->tt_num_changes = tt_num_changes;
if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC)
batadv_ogm_packet->flags |= BATADV_VIS_SERVER;
else
batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER;
if (hard_iface == primary_if &&
atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) {
bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth);
batadv_ogm_packet->gw_flags = bandwidth;
} else {
batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS;
}
batadv_iv_ogm_slide_own_bcast_window(hard_iface); batadv_iv_ogm_slide_own_bcast_window(hard_iface);
batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff, batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
hard_iface->bat_iv.ogm_buff_len, hard_iface, 1, hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
...@@ -798,7 +783,6 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, ...@@ -798,7 +783,6 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
rcu_read_unlock(); rcu_read_unlock();
orig_node->flags = batadv_ogm_packet->flags;
neigh_node->last_seen = jiffies; neigh_node->last_seen = jiffies;
spin_lock_bh(&neigh_node->lq_update_lock); spin_lock_bh(&neigh_node->lq_update_lock);
...@@ -820,11 +804,11 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, ...@@ -820,11 +804,11 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
*/ */
router = batadv_orig_node_get_router(orig_node); router = batadv_orig_node_get_router(orig_node);
if (router == neigh_node) if (router == neigh_node)
goto update_tt; goto out;
/* if this neighbor does not offer a better TQ we won't consider it */ /* if this neighbor does not offer a better TQ we won't consider it */
if (router && (router->tq_avg > neigh_node->tq_avg)) if (router && (router->tq_avg > neigh_node->tq_avg))
goto update_tt; goto out;
/* if the TQ is the same and the link not more symmetric we /* if the TQ is the same and the link not more symmetric we
* won't consider it either * won't consider it either
...@@ -843,35 +827,10 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, ...@@ -843,35 +827,10 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
if (sum_orig >= sum_neigh) if (sum_orig >= sum_neigh)
goto update_tt; goto out;
} }
batadv_update_route(bat_priv, orig_node, neigh_node); batadv_update_route(bat_priv, orig_node, neigh_node);
update_tt:
/* I have to check for transtable changes only if the OGM has been
* sent through a primary interface
*/
if (((batadv_ogm_packet->orig != ethhdr->h_source) &&
(batadv_ogm_packet->header.ttl > 2)) ||
(batadv_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP))
batadv_tt_update_orig(bat_priv, orig_node, tt_buff,
batadv_ogm_packet->tt_num_changes,
batadv_ogm_packet->ttvn,
ntohs(batadv_ogm_packet->tt_crc));
if (orig_node->gw_flags != batadv_ogm_packet->gw_flags)
batadv_gw_node_update(bat_priv, orig_node,
batadv_ogm_packet->gw_flags);
orig_node->gw_flags = batadv_ogm_packet->gw_flags;
/* restart gateway selection if fast or late switching was enabled */
if ((orig_node->gw_flags) &&
(atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw_sel_class) > 2))
batadv_gw_check_election(bat_priv, orig_node);
goto out; goto out;
unlock: unlock:
...@@ -1122,13 +1081,11 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, ...@@ -1122,13 +1081,11 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
is_single_hop_neigh = true; is_single_hop_neigh = true;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, ttvn %u, crc %#.4x, changes %u, tq %d, TTL %d, V %d, IDF %d)\n", "Received BATMAN packet via NB: %pM, IF: %s [%pM] (from OG: %pM, via prev OG: %pM, seqno %u, tq %d, TTL %d, V %d, IDF %d)\n",
ethhdr->h_source, if_incoming->net_dev->name, ethhdr->h_source, if_incoming->net_dev->name,
if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig, if_incoming->net_dev->dev_addr, batadv_ogm_packet->orig,
batadv_ogm_packet->prev_sender, batadv_ogm_packet->prev_sender,
ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->ttvn, ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
ntohs(batadv_ogm_packet->tt_crc),
batadv_ogm_packet->tt_num_changes, batadv_ogm_packet->tq,
batadv_ogm_packet->header.ttl, batadv_ogm_packet->header.ttl,
batadv_ogm_packet->header.version, has_directlink_flag); batadv_ogm_packet->header.version, has_directlink_flag);
...@@ -1254,6 +1211,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, ...@@ -1254,6 +1211,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
goto out; goto out;
} }
batadv_tvlv_ogm_receive(bat_priv, batadv_ogm_packet, orig_node);
/* if sender is a direct neighbor the sender mac equals /* if sender is a direct neighbor the sender mac equals
* originator mac * originator mac
*/ */
...@@ -1350,9 +1309,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, ...@@ -1350,9 +1309,9 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
struct batadv_ogm_packet *batadv_ogm_packet; struct batadv_ogm_packet *batadv_ogm_packet;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
int buff_pos = 0, packet_len; int buff_pos = 0, packet_len;
unsigned char *tt_buff, *packet_buff; unsigned char *tvlv_buff, *packet_buff;
bool ret;
uint8_t *packet_pos; uint8_t *packet_pos;
bool ret;
ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN);
if (!ret) if (!ret)
...@@ -1375,14 +1334,14 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, ...@@ -1375,14 +1334,14 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
/* unpack the aggregated packets and process them one by one */ /* unpack the aggregated packets and process them one by one */
while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
batadv_ogm_packet->tt_num_changes)) { batadv_ogm_packet->tvlv_len)) {
tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN; tvlv_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, batadv_iv_ogm_process(ethhdr, batadv_ogm_packet,
if_incoming); tvlv_buff, if_incoming);
buff_pos += BATADV_OGM_HLEN; buff_pos += BATADV_OGM_HLEN;
buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); buff_pos += ntohs(batadv_ogm_packet->tvlv_len);
packet_pos = packet_buff + buff_pos; packet_pos = packet_buff + buff_pos;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#include "gateway_common.h" #include "gateway_common.h"
#include "gateway_client.h" #include "gateway_client.h"
#include "soft-interface.h" #include "soft-interface.h"
#include "vis.h"
#include "icmp_socket.h" #include "icmp_socket.h"
#include "bridge_loop_avoidance.h" #include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h" #include "distributed-arp-table.h"
...@@ -300,12 +299,6 @@ static int batadv_transtable_local_open(struct inode *inode, struct file *file) ...@@ -300,12 +299,6 @@ static int batadv_transtable_local_open(struct inode *inode, struct file *file)
return single_open(file, batadv_tt_local_seq_print_text, net_dev); return single_open(file, batadv_tt_local_seq_print_text, net_dev);
} }
static int batadv_vis_data_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, batadv_vis_seq_print_text, net_dev);
}
struct batadv_debuginfo { struct batadv_debuginfo {
struct attribute attr; struct attribute attr;
const struct file_operations fops; const struct file_operations fops;
...@@ -356,7 +349,6 @@ static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open); ...@@ -356,7 +349,6 @@ static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
#endif #endif
static BATADV_DEBUGINFO(transtable_local, S_IRUGO, static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
batadv_transtable_local_open); batadv_transtable_local_open);
static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
#ifdef CONFIG_BATMAN_ADV_NC #ifdef CONFIG_BATMAN_ADV_NC
static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open); static BATADV_DEBUGINFO(nc_nodes, S_IRUGO, batadv_nc_nodes_open);
#endif #endif
...@@ -373,7 +365,6 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { ...@@ -373,7 +365,6 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
&batadv_debuginfo_dat_cache, &batadv_debuginfo_dat_cache,
#endif #endif
&batadv_debuginfo_transtable_local, &batadv_debuginfo_transtable_local,
&batadv_debuginfo_vis_data,
#ifdef CONFIG_BATMAN_ADV_NC #ifdef CONFIG_BATMAN_ADV_NC
&batadv_debuginfo_nc_nodes, &batadv_debuginfo_nc_nodes,
#endif #endif
......
...@@ -419,6 +419,10 @@ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res, ...@@ -419,6 +419,10 @@ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
bool ret = false; bool ret = false;
int j; int j;
/* check if orig node candidate is running DAT */
if (!(candidate->capabilities & BATADV_ORIG_CAPA_HAS_DAT))
goto out;
/* Check if this node has already been selected... */ /* Check if this node has already been selected... */
for (j = 0; j < select; j++) for (j = 0; j < select; j++)
if (res[j].orig_node == candidate) if (res[j].orig_node == candidate)
...@@ -625,6 +629,59 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, ...@@ -625,6 +629,59 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
return ret; return ret;
} }
/**
* batadv_dat_tvlv_container_update - update the dat tvlv container after dat
* setting change
* @bat_priv: the bat priv with all the soft interface information
*/
static void batadv_dat_tvlv_container_update(struct batadv_priv *bat_priv)
{
char dat_mode;
dat_mode = atomic_read(&bat_priv->distributed_arp_table);
switch (dat_mode) {
case 0:
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_DAT, 1);
break;
case 1:
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_DAT, 1,
NULL, 0);
break;
}
}
/**
* batadv_dat_status_update - update the dat tvlv container after dat
* setting change
* @net_dev: the soft interface net device
*/
void batadv_dat_status_update(struct net_device *net_dev)
{
struct batadv_priv *bat_priv = netdev_priv(net_dev);
batadv_dat_tvlv_container_update(bat_priv);
}
/**
* batadv_gw_tvlv_ogm_handler_v1 - process incoming dat tvlv container
* @bat_priv: the bat priv with all the soft interface information
* @orig: the orig_node of the ogm
* @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
* @tvlv_value: tvlv buffer containing the gateway data
* @tvlv_value_len: tvlv buffer length
*/
static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
uint8_t flags,
void *tvlv_value,
uint16_t tvlv_value_len)
{
if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_DAT;
else
orig->capabilities |= BATADV_ORIG_CAPA_HAS_DAT;
}
/** /**
* batadv_dat_hash_free - free the local DAT hash table * batadv_dat_hash_free - free the local DAT hash table
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
...@@ -657,6 +714,10 @@ int batadv_dat_init(struct batadv_priv *bat_priv) ...@@ -657,6 +714,10 @@ int batadv_dat_init(struct batadv_priv *bat_priv)
batadv_dat_start_timer(bat_priv); batadv_dat_start_timer(bat_priv);
batadv_tvlv_handler_register(bat_priv, batadv_dat_tvlv_ogm_handler_v1,
NULL, BATADV_TVLV_DAT, 1,
BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
batadv_dat_tvlv_container_update(bat_priv);
return 0; return 0;
} }
...@@ -666,6 +727,9 @@ int batadv_dat_init(struct batadv_priv *bat_priv) ...@@ -666,6 +727,9 @@ int batadv_dat_init(struct batadv_priv *bat_priv)
*/ */
void batadv_dat_free(struct batadv_priv *bat_priv) void batadv_dat_free(struct batadv_priv *bat_priv)
{ {
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_DAT, 1);
batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_DAT, 1);
cancel_delayed_work_sync(&bat_priv->dat.work); cancel_delayed_work_sync(&bat_priv->dat.work);
batadv_dat_hash_free(bat_priv); batadv_dat_hash_free(bat_priv);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
void batadv_dat_status_update(struct net_device *net_dev);
bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
struct sk_buff *skb); struct sk_buff *skb);
bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
...@@ -98,6 +99,10 @@ static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv, ...@@ -98,6 +99,10 @@ static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
#else #else
static inline void batadv_dat_status_update(struct net_device *net_dev)
{
}
static inline bool static inline bool
batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
struct sk_buff *skb) struct sk_buff *skb)
......
...@@ -118,7 +118,6 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) ...@@ -118,7 +118,6 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
uint32_t max_gw_factor = 0, tmp_gw_factor = 0; uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
uint32_t gw_divisor; uint32_t gw_divisor;
uint8_t max_tq = 0; uint8_t max_tq = 0;
int down, up;
uint8_t tq_avg; uint8_t tq_avg;
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
...@@ -142,10 +141,9 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) ...@@ -142,10 +141,9 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
switch (atomic_read(&bat_priv->gw_sel_class)) { switch (atomic_read(&bat_priv->gw_sel_class)) {
case 1: /* fast connection */ case 1: /* fast connection */
batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, tmp_gw_factor = tq_avg * tq_avg;
&down, &up); tmp_gw_factor *= gw_node->bandwidth_down;
tmp_gw_factor *= 100 * 100;
tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100;
tmp_gw_factor /= gw_divisor; tmp_gw_factor /= gw_divisor;
if ((tmp_gw_factor > max_gw_factor) || if ((tmp_gw_factor > max_gw_factor) ||
...@@ -258,16 +256,22 @@ void batadv_gw_election(struct batadv_priv *bat_priv) ...@@ -258,16 +256,22 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
NULL); NULL);
} else if ((!curr_gw) && (next_gw)) { } else if ((!curr_gw) && (next_gw)) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Adding route to gateway %pM (gw_flags: %i, tq: %i)\n", "Adding route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
next_gw->orig_node->orig, next_gw->orig_node->orig,
next_gw->orig_node->gw_flags, router->tq_avg); next_gw->bandwidth_down / 10,
next_gw->bandwidth_down % 10,
next_gw->bandwidth_up / 10,
next_gw->bandwidth_up % 10, router->tq_avg);
batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD, batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_ADD,
gw_addr); gw_addr);
} else { } else {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Changing route to gateway %pM (gw_flags: %i, tq: %i)\n", "Changing route to gateway %pM (bandwidth: %u.%u/%u.%u MBit, tq: %i)\n",
next_gw->orig_node->orig, next_gw->orig_node->orig,
next_gw->orig_node->gw_flags, router->tq_avg); next_gw->bandwidth_down / 10,
next_gw->bandwidth_down % 10,
next_gw->bandwidth_up / 10,
next_gw->bandwidth_up % 10, router->tq_avg);
batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE, batadv_throw_uevent(bat_priv, BATADV_UEV_GW, BATADV_UEV_CHANGE,
gw_addr); gw_addr);
} }
...@@ -337,12 +341,20 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, ...@@ -337,12 +341,20 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
return; return;
} }
/**
* batadv_gw_node_add - add gateway node to list of available gateways
* @bat_priv: the bat priv with all the soft interface information
* @orig_node: originator announcing gateway capabilities
* @gateway: announced bandwidth information
*/
static void batadv_gw_node_add(struct batadv_priv *bat_priv, static void batadv_gw_node_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_node,
uint8_t new_gwflags) struct batadv_tvlv_gateway_data *gateway)
{ {
struct batadv_gw_node *gw_node; struct batadv_gw_node *gw_node;
int down, up;
if (gateway->bandwidth_down == 0)
return;
gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC);
if (!gw_node) if (!gw_node)
...@@ -356,73 +368,116 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, ...@@ -356,73 +368,116 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list);
spin_unlock_bh(&bat_priv->gw.list_lock); spin_unlock_bh(&bat_priv->gw.list_lock);
batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up);
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Found new gateway %pM -> gw_class: %i - %i%s/%i%s\n", "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
orig_node->orig, new_gwflags, orig_node->orig,
(down > 2048 ? down / 1024 : down), ntohl(gateway->bandwidth_down) / 10,
(down > 2048 ? "MBit" : "KBit"), ntohl(gateway->bandwidth_down) % 10,
(up > 2048 ? up / 1024 : up), ntohl(gateway->bandwidth_up) / 10,
(up > 2048 ? "MBit" : "KBit")); ntohl(gateway->bandwidth_up) % 10);
} }
/**
* batadv_gw_node_get - retrieve gateway node from list of available gateways
* @bat_priv: the bat priv with all the soft interface information
* @orig_node: originator announcing gateway capabilities
*
* Returns gateway node if found or NULL otherwise.
*/
static struct batadv_gw_node *
batadv_gw_node_get(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node)
{
struct batadv_gw_node *gw_node_tmp, *gw_node = NULL;
rcu_read_lock();
hlist_for_each_entry_rcu(gw_node_tmp, &bat_priv->gw.list, list) {
if (gw_node_tmp->orig_node != orig_node)
continue;
if (gw_node_tmp->deleted)
continue;
if (!atomic_inc_not_zero(&gw_node_tmp->refcount))
continue;
gw_node = gw_node_tmp;
break;
}
rcu_read_unlock();
return gw_node;
}
/**
* batadv_gw_node_update - update list of available gateways with changed
* bandwidth information
* @bat_priv: the bat priv with all the soft interface information
* @orig_node: originator announcing gateway capabilities
* @gateway: announced bandwidth information
*/
void batadv_gw_node_update(struct batadv_priv *bat_priv, void batadv_gw_node_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_node,
uint8_t new_gwflags) struct batadv_tvlv_gateway_data *gateway)
{ {
struct batadv_gw_node *gw_node, *curr_gw; struct batadv_gw_node *gw_node, *curr_gw = NULL;
/* Note: We don't need a NULL check here, since curr_gw never gets gw_node = batadv_gw_node_get(bat_priv, orig_node);
* dereferenced. If curr_gw is NULL we also should not exit as we may if (!gw_node) {
* have this gateway in our list (duplication check!) even though we batadv_gw_node_add(bat_priv, orig_node, gateway);
* have no currently selected gateway. goto out;
*/ }
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
rcu_read_lock(); if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) &&
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.list, list) { (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up)))
if (gw_node->orig_node != orig_node) goto out;
continue;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Gateway class of originator %pM changed from %i to %i\n", "Gateway bandwidth of originator %pM changed from %u.%u/%u.%u MBit to %u.%u/%u.%u MBit\n",
orig_node->orig, gw_node->orig_node->gw_flags, orig_node->orig,
new_gwflags); gw_node->bandwidth_down / 10,
gw_node->bandwidth_down % 10,
gw_node->bandwidth_up / 10,
gw_node->bandwidth_up % 10,
ntohl(gateway->bandwidth_down) / 10,
ntohl(gateway->bandwidth_down) % 10,
ntohl(gateway->bandwidth_up) / 10,
ntohl(gateway->bandwidth_up) % 10);
gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
gw_node->deleted = 0; gw_node->deleted = 0;
if (ntohl(gateway->bandwidth_down) == 0) {
if (new_gwflags == BATADV_NO_FLAGS) {
gw_node->deleted = jiffies; gw_node->deleted = jiffies;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Gateway %pM removed from gateway list\n", "Gateway %pM removed from gateway list\n",
orig_node->orig); orig_node->orig);
/* Note: We don't need a NULL check here, since curr_gw never
* gets dereferenced.
*/
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
if (gw_node == curr_gw) if (gw_node == curr_gw)
goto deselect;
}
goto unlock;
}
if (new_gwflags == BATADV_NO_FLAGS)
goto unlock;
batadv_gw_node_add(bat_priv, orig_node, new_gwflags);
goto unlock;
deselect:
batadv_gw_deselect(bat_priv); batadv_gw_deselect(bat_priv);
unlock: }
rcu_read_unlock();
out:
if (curr_gw) if (curr_gw)
batadv_gw_node_free_ref(curr_gw); batadv_gw_node_free_ref(curr_gw);
if (gw_node)
batadv_gw_node_free_ref(gw_node);
} }
void batadv_gw_node_delete(struct batadv_priv *bat_priv, void batadv_gw_node_delete(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node) struct batadv_orig_node *orig_node)
{ {
batadv_gw_node_update(bat_priv, orig_node, 0); struct batadv_tvlv_gateway_data gateway;
gateway.bandwidth_down = 0;
gateway.bandwidth_up = 0;
batadv_gw_node_update(bat_priv, orig_node, &gateway);
} }
void batadv_gw_node_purge(struct batadv_priv *bat_priv) void batadv_gw_node_purge(struct batadv_priv *bat_priv)
...@@ -467,9 +522,7 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv, ...@@ -467,9 +522,7 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
{ {
struct batadv_gw_node *curr_gw; struct batadv_gw_node *curr_gw;
struct batadv_neigh_node *router; struct batadv_neigh_node *router;
int down, up, ret = -1; int ret = -1;
batadv_gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
router = batadv_orig_node_get_router(gw_node->orig_node); router = batadv_orig_node_get_router(gw_node->orig_node);
if (!router) if (!router)
...@@ -477,16 +530,15 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv, ...@@ -477,16 +530,15 @@ static int batadv_write_buffer_text(struct batadv_priv *bat_priv,
curr_gw = batadv_gw_get_selected_gw_node(bat_priv); curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %u.%u/%u.%u MBit\n",
(curr_gw == gw_node ? "=>" : " "), (curr_gw == gw_node ? "=>" : " "),
gw_node->orig_node->orig, gw_node->orig_node->orig,
router->tq_avg, router->addr, router->tq_avg, router->addr,
router->if_incoming->net_dev->name, router->if_incoming->net_dev->name,
gw_node->orig_node->gw_flags, gw_node->bandwidth_down / 10,
(down > 2048 ? down / 1024 : down), gw_node->bandwidth_down % 10,
(down > 2048 ? "MBit" : "KBit"), gw_node->bandwidth_up / 10,
(up > 2048 ? up / 1024 : up), gw_node->bandwidth_up % 10);
(up > 2048 ? "MBit" : "KBit"));
batadv_neigh_node_free_ref(router); batadv_neigh_node_free_ref(router);
if (curr_gw) if (curr_gw)
...@@ -508,7 +560,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) ...@@ -508,7 +560,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
goto out; goto out;
seq_printf(seq, seq_printf(seq,
" %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n", " %-12s (%s/%i) %17s [%10s]: advertised uplink bandwidth ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
"Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Gateway", "#", BATADV_TQ_MAX_VALUE, "Nexthop", "outgoingIF",
BATADV_SOURCE_VERSION, primary_if->net_dev->name, BATADV_SOURCE_VERSION, primary_if->net_dev->name,
primary_if->net_dev->dev_addr, net_dev->name); primary_if->net_dev->dev_addr, net_dev->name);
...@@ -675,7 +727,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, ...@@ -675,7 +727,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
{ {
struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL; struct batadv_neigh_node *neigh_curr = NULL, *neigh_old = NULL;
struct batadv_orig_node *orig_dst_node = NULL; struct batadv_orig_node *orig_dst_node = NULL;
struct batadv_gw_node *curr_gw = NULL; struct batadv_gw_node *gw_node = NULL, *curr_gw = NULL;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
bool ret, out_of_range = false; bool ret, out_of_range = false;
unsigned int header_len = 0; unsigned int header_len = 0;
...@@ -691,7 +743,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, ...@@ -691,7 +743,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
if (!orig_dst_node) if (!orig_dst_node)
goto out; goto out;
if (!orig_dst_node->gw_flags) gw_node = batadv_gw_node_get(bat_priv, orig_dst_node);
if (!gw_node->bandwidth_down == 0)
goto out; goto out;
ret = batadv_is_type_dhcprequest(skb, header_len); ret = batadv_is_type_dhcprequest(skb, header_len);
...@@ -742,6 +795,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, ...@@ -742,6 +795,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
batadv_orig_node_free_ref(orig_dst_node); batadv_orig_node_free_ref(orig_dst_node);
if (curr_gw) if (curr_gw)
batadv_gw_node_free_ref(curr_gw); batadv_gw_node_free_ref(curr_gw);
if (gw_node)
batadv_gw_node_free_ref(gw_node);
if (neigh_old) if (neigh_old)
batadv_neigh_node_free_ref(neigh_old); batadv_neigh_node_free_ref(neigh_old);
if (neigh_curr) if (neigh_curr)
......
...@@ -29,7 +29,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv, ...@@ -29,7 +29,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node); struct batadv_orig_node *orig_node);
void batadv_gw_node_update(struct batadv_priv *bat_priv, void batadv_gw_node_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_node,
uint8_t new_gwflags); struct batadv_tvlv_gateway_data *gateway);
void batadv_gw_node_delete(struct batadv_priv *bat_priv, void batadv_gw_node_delete(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node); struct batadv_orig_node *orig_node);
void batadv_gw_node_purge(struct batadv_priv *bat_priv); void batadv_gw_node_purge(struct batadv_priv *bat_priv);
......
...@@ -21,64 +21,23 @@ ...@@ -21,64 +21,23 @@
#include "gateway_common.h" #include "gateway_common.h"
#include "gateway_client.h" #include "gateway_client.h"
/* calculates the gateway class from kbit */ /**
static void batadv_kbit_to_gw_bandwidth(int down, int up, long *gw_srv_class) * batadv_parse_gw_bandwidth - parse supplied string buffer to extract download
{ * and upload bandwidth information
int mdown = 0, tdown, tup, difference; * @net_dev: the soft interface net device
uint8_t sbit, part; * @buff: string buffer to parse
* @down: pointer holding the returned download bandwidth information
*gw_srv_class = 0; * @up: pointer holding the returned upload bandwidth information
difference = 0x0FFFFFFF; *
* Returns false on parse error and true otherwise.
/* test all downspeeds */ */
for (sbit = 0; sbit < 2; sbit++) {
for (part = 0; part < 16; part++) {
tdown = 32 * (sbit + 2) * (1 << part);
if (abs(tdown - down) < difference) {
*gw_srv_class = (sbit << 7) + (part << 3);
difference = abs(tdown - down);
mdown = tdown;
}
}
}
/* test all upspeeds */
difference = 0x0FFFFFFF;
for (part = 0; part < 8; part++) {
tup = ((part + 1) * (mdown)) / 8;
if (abs(tup - up) < difference) {
*gw_srv_class = (*gw_srv_class & 0xF8) | part;
difference = abs(tup - up);
}
}
}
/* returns the up and downspeeds in kbit, calculated from the class */
void batadv_gw_bandwidth_to_kbit(uint8_t gw_srv_class, int *down, int *up)
{
int sbit = (gw_srv_class & 0x80) >> 7;
int dpart = (gw_srv_class & 0x78) >> 3;
int upart = (gw_srv_class & 0x07);
if (!gw_srv_class) {
*down = 0;
*up = 0;
return;
}
*down = 32 * (sbit + 2) * (1 << dpart);
*up = ((upart + 1) * (*down)) / 8;
}
static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
int *up, int *down) uint32_t *down, uint32_t *up)
{ {
int ret, multi = 1; enum batadv_bandwidth_units bw_unit_type = BATADV_BW_UNIT_KBIT;
char *slash_ptr, *tmp_ptr; char *slash_ptr, *tmp_ptr;
long ldown, lup; long ldown, lup;
int ret;
slash_ptr = strchr(buff, '/'); slash_ptr = strchr(buff, '/');
if (slash_ptr) if (slash_ptr)
...@@ -88,10 +47,10 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, ...@@ -88,10 +47,10 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
tmp_ptr = buff + strlen(buff) - 4; tmp_ptr = buff + strlen(buff) - 4;
if (strnicmp(tmp_ptr, "mbit", 4) == 0) if (strnicmp(tmp_ptr, "mbit", 4) == 0)
multi = 1024; bw_unit_type = BATADV_BW_UNIT_MBIT;
if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
(multi > 1)) (bw_unit_type == BATADV_BW_UNIT_MBIT))
*tmp_ptr = '\0'; *tmp_ptr = '\0';
} }
...@@ -103,20 +62,28 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, ...@@ -103,20 +62,28 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
return false; return false;
} }
*down = ldown * multi; switch (bw_unit_type) {
case BATADV_BW_UNIT_MBIT:
*down = ldown * 10;
break;
case BATADV_BW_UNIT_KBIT:
default:
*down = ldown / 100;
break;
}
/* we also got some upload info */ /* we also got some upload info */
if (slash_ptr) { if (slash_ptr) {
multi = 1; bw_unit_type = BATADV_BW_UNIT_KBIT;
if (strlen(slash_ptr + 1) > 4) { if (strlen(slash_ptr + 1) > 4) {
tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1); tmp_ptr = slash_ptr + 1 - 4 + strlen(slash_ptr + 1);
if (strnicmp(tmp_ptr, "mbit", 4) == 0) if (strnicmp(tmp_ptr, "mbit", 4) == 0)
multi = 1024; bw_unit_type = BATADV_BW_UNIT_MBIT;
if ((strnicmp(tmp_ptr, "kbit", 4) == 0) || if ((strnicmp(tmp_ptr, "kbit", 4) == 0) ||
(multi > 1)) (bw_unit_type == BATADV_BW_UNIT_MBIT))
*tmp_ptr = '\0'; *tmp_ptr = '\0';
} }
...@@ -128,52 +95,149 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff, ...@@ -128,52 +95,149 @@ static bool batadv_parse_gw_bandwidth(struct net_device *net_dev, char *buff,
return false; return false;
} }
*up = lup * multi; switch (bw_unit_type) {
case BATADV_BW_UNIT_MBIT:
*up = lup * 10;
break;
case BATADV_BW_UNIT_KBIT:
default:
*up = lup / 100;
break;
}
} }
return true; return true;
} }
/**
* batadv_gw_tvlv_container_update - update the gw tvlv container after gateway
* setting change
* @bat_priv: the bat priv with all the soft interface information
*/
void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
{
struct batadv_tvlv_gateway_data gw;
uint32_t down, up;
char gw_mode;
gw_mode = atomic_read(&bat_priv->gw_mode);
switch (gw_mode) {
case BATADV_GW_MODE_OFF:
case BATADV_GW_MODE_CLIENT:
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
break;
case BATADV_GW_MODE_SERVER:
down = atomic_read(&bat_priv->gw.bandwidth_down);
up = atomic_read(&bat_priv->gw.bandwidth_up);
gw.bandwidth_down = htonl(down);
gw.bandwidth_up = htonl(up);
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1,
&gw, sizeof(gw));
break;
}
}
ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
size_t count) size_t count)
{ {
struct batadv_priv *bat_priv = netdev_priv(net_dev); struct batadv_priv *bat_priv = netdev_priv(net_dev);
long gw_bandwidth_tmp = 0; uint32_t down_curr, up_curr, down_new = 0, up_new = 0;
int up = 0, down = 0;
bool ret; bool ret;
ret = batadv_parse_gw_bandwidth(net_dev, buff, &up, &down); down_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_down);
up_curr = (unsigned int)atomic_read(&bat_priv->gw.bandwidth_up);
ret = batadv_parse_gw_bandwidth(net_dev, buff, &down_new, &up_new);
if (!ret) if (!ret)
goto end; goto end;
if ((!down) || (down < 256)) if (!down_new)
down = 2000; down_new = 1;
if (!up)
up = down / 5;
batadv_kbit_to_gw_bandwidth(down, up, &gw_bandwidth_tmp); if (!up_new)
up_new = down_new / 5;
/* the gw bandwidth we guessed above might not match the given if (!up_new)
* speeds, hence we need to calculate it back to show the number up_new = 1;
* that is going to be propagated
*/
batadv_gw_bandwidth_to_kbit((uint8_t)gw_bandwidth_tmp, &down, &up);
if (atomic_read(&bat_priv->gw_bandwidth) == gw_bandwidth_tmp) if ((down_curr == down_new) && (up_curr == up_new))
return count; return count;
batadv_gw_deselect(bat_priv); batadv_gw_deselect(bat_priv);
batadv_info(net_dev, batadv_info(net_dev,
"Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s)\n", "Changing gateway bandwidth from: '%u.%u/%u.%u MBit' to: '%u.%u/%u.%u MBit'\n",
atomic_read(&bat_priv->gw_bandwidth), gw_bandwidth_tmp, down_curr / 10, down_curr % 10, up_curr / 10, up_curr % 10,
(down > 2048 ? down / 1024 : down), down_new / 10, down_new % 10, up_new / 10, up_new % 10);
(down > 2048 ? "MBit" : "KBit"),
(up > 2048 ? up / 1024 : up),
(up > 2048 ? "MBit" : "KBit"));
atomic_set(&bat_priv->gw_bandwidth, gw_bandwidth_tmp); atomic_set(&bat_priv->gw.bandwidth_down, down_new);
atomic_set(&bat_priv->gw.bandwidth_up, up_new);
batadv_gw_tvlv_container_update(bat_priv);
end: end:
return count; return count;
} }
/**
* batadv_gw_tvlv_ogm_handler_v1 - process incoming gateway tvlv container
* @bat_priv: the bat priv with all the soft interface information
* @orig: the orig_node of the ogm
* @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
* @tvlv_value: tvlv buffer containing the gateway data
* @tvlv_value_len: tvlv buffer length
*/
static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
uint8_t flags,
void *tvlv_value,
uint16_t tvlv_value_len)
{
struct batadv_tvlv_gateway_data gateway, *gateway_ptr;
/* only fetch the tvlv value if the handler wasn't called via the
* CIFNOTFND flag and if there is data to fetch
*/
if ((flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) ||
(tvlv_value_len < sizeof(gateway))) {
gateway.bandwidth_down = 0;
gateway.bandwidth_up = 0;
} else {
gateway_ptr = tvlv_value;
gateway.bandwidth_down = gateway_ptr->bandwidth_down;
gateway.bandwidth_up = gateway_ptr->bandwidth_up;
if ((gateway.bandwidth_down == 0) ||
(gateway.bandwidth_up == 0)) {
gateway.bandwidth_down = 0;
gateway.bandwidth_up = 0;
}
}
batadv_gw_node_update(bat_priv, orig, &gateway);
/* restart gateway selection if fast or late switching was enabled */
if ((gateway.bandwidth_down != 0) &&
(atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_CLIENT) &&
(atomic_read(&bat_priv->gw_sel_class) > 2))
batadv_gw_check_election(bat_priv, orig);
}
/**
* batadv_gw_init - initialise the gateway handling internals
* @bat_priv: the bat priv with all the soft interface information
*/
void batadv_gw_init(struct batadv_priv *bat_priv)
{
batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1,
NULL, BATADV_TVLV_GW, 1,
BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
}
/**
* batadv_gw_free - free the gateway handling internals
* @bat_priv: the bat priv with all the soft interface information
*/
void batadv_gw_free(struct batadv_priv *bat_priv)
{
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_GW, 1);
}
...@@ -26,12 +26,24 @@ enum batadv_gw_modes { ...@@ -26,12 +26,24 @@ enum batadv_gw_modes {
BATADV_GW_MODE_SERVER, BATADV_GW_MODE_SERVER,
}; };
/**
* enum batadv_bandwidth_units - bandwidth unit types
* @BATADV_BW_UNIT_KBIT: unit type kbit
* @BATADV_BW_UNIT_MBIT: unit type mbit
*/
enum batadv_bandwidth_units {
BATADV_BW_UNIT_KBIT,
BATADV_BW_UNIT_MBIT,
};
#define BATADV_GW_MODE_OFF_NAME "off" #define BATADV_GW_MODE_OFF_NAME "off"
#define BATADV_GW_MODE_CLIENT_NAME "client" #define BATADV_GW_MODE_CLIENT_NAME "client"
#define BATADV_GW_MODE_SERVER_NAME "server" #define BATADV_GW_MODE_SERVER_NAME "server"
void batadv_gw_bandwidth_to_kbit(uint8_t gw_class, int *down, int *up);
ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff, ssize_t batadv_gw_bandwidth_set(struct net_device *net_dev, char *buff,
size_t count); size_t count);
void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv);
void batadv_gw_init(struct batadv_priv *bat_priv);
void batadv_gw_free(struct batadv_priv *bat_priv);
#endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */ #endif /* _NET_BATMAN_ADV_GATEWAY_COMMON_H_ */
...@@ -194,22 +194,13 @@ batadv_hardif_get_active(const struct net_device *soft_iface) ...@@ -194,22 +194,13 @@ batadv_hardif_get_active(const struct net_device *soft_iface)
static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
struct batadv_hard_iface *oldif) struct batadv_hard_iface *oldif)
{ {
struct batadv_vis_packet *vis_packet;
struct batadv_hard_iface *primary_if; struct batadv_hard_iface *primary_if;
struct sk_buff *skb;
primary_if = batadv_primary_if_get_selected(bat_priv); primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if) if (!primary_if)
goto out; goto out;
batadv_dat_init_own_addr(bat_priv, primary_if); batadv_dat_init_own_addr(bat_priv, primary_if);
skb = bat_priv->vis.my_info->skb_packet;
vis_packet = (struct batadv_vis_packet *)skb->data;
memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
memcpy(vis_packet->sender_orig,
primary_if->net_dev->dev_addr, ETH_ALEN);
batadv_bla_update_orig_address(bat_priv, primary_if, oldif); batadv_bla_update_orig_address(bat_priv, primary_if, oldif);
out: out:
if (primary_if) if (primary_if)
......
This diff is collapsed.
...@@ -86,8 +86,6 @@ ...@@ -86,8 +86,6 @@
/* numbers of originator to contact for any PUT/GET DHT operation */ /* numbers of originator to contact for any PUT/GET DHT operation */
#define BATADV_DAT_CANDIDATES_NUM 3 #define BATADV_DAT_CANDIDATES_NUM 3
#define BATADV_VIS_INTERVAL 5000 /* 5 seconds */
/* how much worse secondary interfaces may be to be considered as bonding /* how much worse secondary interfaces may be to be considered as bonding
* candidates * candidates
*/ */
...@@ -326,4 +324,39 @@ static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv, ...@@ -326,4 +324,39 @@ static inline uint64_t batadv_sum_counter(struct batadv_priv *bat_priv,
*/ */
#define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0])) #define BATADV_SKB_CB(__skb) ((struct batadv_skb_cb *)&((__skb)->cb[0]))
void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
uint8_t type, uint8_t version,
void *tvlv_value, uint16_t tvlv_value_len);
uint16_t batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
unsigned char **packet_buff,
int *packet_buff_len,
int packet_min_len);
void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
struct batadv_ogm_packet *batadv_ogm_packet,
struct batadv_orig_node *orig_node);
void batadv_tvlv_container_unregister(struct batadv_priv *bat_priv,
uint8_t type, uint8_t version);
void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
void (*optr)(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
uint8_t flags,
void *tvlv_value,
uint16_t tvlv_value_len),
int (*uptr)(struct batadv_priv *bat_priv,
uint8_t *src, uint8_t *dst,
void *tvlv_value,
uint16_t tvlv_value_len),
uint8_t type, uint8_t version, uint8_t flags);
void batadv_tvlv_handler_unregister(struct batadv_priv *bat_priv,
uint8_t type, uint8_t version);
int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
bool ogm_source,
struct batadv_orig_node *orig_node,
uint8_t *src, uint8_t *dst,
void *tvlv_buff, uint16_t tvlv_buff_len);
void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
uint8_t *dst, uint8_t type, uint8_t version,
void *tvlv_value, uint16_t tvlv_value_len);
#endif /* _NET_BATMAN_ADV_MAIN_H_ */ #endif /* _NET_BATMAN_ADV_MAIN_H_ */
...@@ -58,6 +58,59 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv) ...@@ -58,6 +58,59 @@ static void batadv_nc_start_timer(struct batadv_priv *bat_priv)
msecs_to_jiffies(10)); msecs_to_jiffies(10));
} }
/**
* batadv_nc_tvlv_container_update - update the network coding tvlv container
* after network coding setting change
* @bat_priv: the bat priv with all the soft interface information
*/
static void batadv_nc_tvlv_container_update(struct batadv_priv *bat_priv)
{
char nc_mode;
nc_mode = atomic_read(&bat_priv->network_coding);
switch (nc_mode) {
case 0:
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1);
break;
case 1:
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_NC, 1,
NULL, 0);
break;
}
}
/**
* batadv_nc_status_update - update the network coding tvlv container after
* network coding setting change
* @net_dev: the soft interface net device
*/
void batadv_nc_status_update(struct net_device *net_dev)
{
struct batadv_priv *bat_priv = netdev_priv(net_dev);
batadv_nc_tvlv_container_update(bat_priv);
}
/**
* batadv_nc_tvlv_ogm_handler_v1 - process incoming nc tvlv container
* @bat_priv: the bat priv with all the soft interface information
* @orig: the orig_node of the ogm
* @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags)
* @tvlv_value: tvlv buffer containing the gateway data
* @tvlv_value_len: tvlv buffer length
*/
static void batadv_nc_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
uint8_t flags,
void *tvlv_value,
uint16_t tvlv_value_len)
{
if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND)
orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_NC;
else
orig->capabilities |= BATADV_ORIG_CAPA_HAS_NC;
}
/** /**
* batadv_nc_mesh_init - initialise coding hash table and start house keeping * batadv_nc_mesh_init - initialise coding hash table and start house keeping
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
...@@ -87,6 +140,10 @@ int batadv_nc_mesh_init(struct batadv_priv *bat_priv) ...@@ -87,6 +140,10 @@ int batadv_nc_mesh_init(struct batadv_priv *bat_priv)
INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker); INIT_DELAYED_WORK(&bat_priv->nc.work, batadv_nc_worker);
batadv_nc_start_timer(bat_priv); batadv_nc_start_timer(bat_priv);
batadv_tvlv_handler_register(bat_priv, batadv_nc_tvlv_ogm_handler_v1,
NULL, BATADV_TVLV_NC, 1,
BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
batadv_nc_tvlv_container_update(bat_priv);
return 0; return 0;
err: err:
...@@ -802,6 +859,10 @@ void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, ...@@ -802,6 +859,10 @@ void batadv_nc_update_nc_node(struct batadv_priv *bat_priv,
if (!atomic_read(&bat_priv->network_coding)) if (!atomic_read(&bat_priv->network_coding))
goto out; goto out;
/* check if orig node is network coding enabled */
if (!(orig_node->capabilities & BATADV_ORIG_CAPA_HAS_NC))
goto out;
/* accept ogms from 'good' neighbors and single hop neighbors */ /* accept ogms from 'good' neighbors and single hop neighbors */
if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) && if (!batadv_can_nc_with_orig(bat_priv, orig_node, ogm_packet) &&
!is_single_hop_neigh) !is_single_hop_neigh)
...@@ -1735,6 +1796,8 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb, ...@@ -1735,6 +1796,8 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb,
*/ */
void batadv_nc_mesh_free(struct batadv_priv *bat_priv) void batadv_nc_mesh_free(struct batadv_priv *bat_priv)
{ {
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_NC, 1);
batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_NC, 1);
cancel_delayed_work_sync(&bat_priv->nc.work); cancel_delayed_work_sync(&bat_priv->nc.work);
batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL); batadv_nc_purge_paths(bat_priv, bat_priv->nc.coding_hash, NULL);
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#ifdef CONFIG_BATMAN_ADV_NC #ifdef CONFIG_BATMAN_ADV_NC
void batadv_nc_status_update(struct net_device *net_dev);
int batadv_nc_init(void); int batadv_nc_init(void);
int batadv_nc_mesh_init(struct batadv_priv *bat_priv); int batadv_nc_mesh_init(struct batadv_priv *bat_priv);
void batadv_nc_mesh_free(struct batadv_priv *bat_priv); void batadv_nc_mesh_free(struct batadv_priv *bat_priv);
...@@ -47,6 +48,10 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv); ...@@ -47,6 +48,10 @@ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv);
#else /* ifdef CONFIG_BATMAN_ADV_NC */ #else /* ifdef CONFIG_BATMAN_ADV_NC */
static inline void batadv_nc_status_update(struct net_device *net_dev)
{
}
static inline int batadv_nc_init(void) static inline int batadv_nc_init(void)
{ {
return 0; return 0;
......
...@@ -388,9 +388,7 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv) ...@@ -388,9 +388,7 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
hlist_for_each_entry_safe(orig_node, node_tmp, hlist_for_each_entry_safe(orig_node, node_tmp,
head, hash_entry) { head, hash_entry) {
if (batadv_purge_orig_node(bat_priv, orig_node)) { if (batadv_purge_orig_node(bat_priv, orig_node)) {
if (orig_node->gw_flags) batadv_gw_node_delete(bat_priv, orig_node);
batadv_gw_node_delete(bat_priv,
orig_node);
hlist_del_rcu(&orig_node->hash_entry); hlist_del_rcu(&orig_node->hash_entry);
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
continue; continue;
......
...@@ -20,17 +20,34 @@ ...@@ -20,17 +20,34 @@
#ifndef _NET_BATMAN_ADV_PACKET_H_ #ifndef _NET_BATMAN_ADV_PACKET_H_
#define _NET_BATMAN_ADV_PACKET_H_ #define _NET_BATMAN_ADV_PACKET_H_
/**
* enum batadv_packettype - types for batman-adv encapsulated packets
* @BATADV_IV_OGM: originator messages for B.A.T.M.A.N. IV
* @BATADV_BCAST: broadcast packets carrying broadcast payload
* @BATADV_CODED: network coded packets
*
* @BATADV_UNICAST: unicast packets carrying unicast payload traffic
* @BATADV_UNICAST_FRAG: unicast packets carrying a fragment of the original
* payload packet
* @BATADV_UNICAST_4ADDR: unicast packet including the originator address of
* the sender
* @BATADV_ICMP: unicast packet like IP ICMP used for ping or traceroute
* @BATADV_UNICAST_TVLV: unicast packet carrying TVLV containers
*/
enum batadv_packettype { enum batadv_packettype {
BATADV_IV_OGM = 0x01, /* 0x00 - 0x3f: local packets or special rules for handling */
BATADV_ICMP = 0x02, BATADV_IV_OGM = 0x00,
BATADV_UNICAST = 0x03, BATADV_BCAST = 0x01,
BATADV_BCAST = 0x04, BATADV_CODED = 0x02,
BATADV_VIS = 0x05, /* 0x40 - 0x7f: unicast */
BATADV_UNICAST_FRAG = 0x06, #define BATADV_UNICAST_MIN 0x40
BATADV_TT_QUERY = 0x07, BATADV_UNICAST = 0x40,
BATADV_ROAM_ADV = 0x08, BATADV_UNICAST_FRAG = 0x41,
BATADV_UNICAST_4ADDR = 0x09, BATADV_UNICAST_4ADDR = 0x42,
BATADV_CODED = 0x0a, BATADV_ICMP = 0x43,
BATADV_UNICAST_TVLV = 0x44,
#define BATADV_UNICAST_MAX 0x7f
/* 0x80 - 0xff: reserved */
}; };
/** /**
...@@ -48,13 +65,21 @@ enum batadv_subtype { ...@@ -48,13 +65,21 @@ enum batadv_subtype {
}; };
/* this file is included by batctl which needs these defines */ /* this file is included by batctl which needs these defines */
#define BATADV_COMPAT_VERSION 14 #define BATADV_COMPAT_VERSION 15
/**
* enum batadv_iv_flags - flags used in B.A.T.M.A.N. IV OGM packets
* @BATADV_NOT_BEST_NEXT_HOP: flag is set when ogm packet is forwarded and was
* previously received from someone else than the best neighbor.
* @BATADV_PRIMARIES_FIRST_HOP: flag is set when the primary interface address
* is used, and the packet travels its first hop.
* @BATADV_DIRECTLINK: flag is for the first hop or if rebroadcasted from a
* one hop neighbor on the interface where it was originally received.
*/
enum batadv_iv_flags { enum batadv_iv_flags {
BATADV_NOT_BEST_NEXT_HOP = BIT(3), BATADV_NOT_BEST_NEXT_HOP = BIT(0),
BATADV_PRIMARIES_FIRST_HOP = BIT(4), BATADV_PRIMARIES_FIRST_HOP = BIT(1),
BATADV_VIS_SERVER = BIT(5), BATADV_DIRECTLINK = BIT(2),
BATADV_DIRECTLINK = BIT(6),
}; };
/* ICMP message types */ /* ICMP message types */
...@@ -66,29 +91,27 @@ enum batadv_icmp_packettype { ...@@ -66,29 +91,27 @@ enum batadv_icmp_packettype {
BATADV_PARAMETER_PROBLEM = 12, BATADV_PARAMETER_PROBLEM = 12,
}; };
/* vis defines */
enum batadv_vis_packettype {
BATADV_VIS_TYPE_SERVER_SYNC = 0,
BATADV_VIS_TYPE_CLIENT_UPDATE = 1,
};
/* fragmentation defines */ /* fragmentation defines */
enum batadv_unicast_frag_flags { enum batadv_unicast_frag_flags {
BATADV_UNI_FRAG_HEAD = BIT(0), BATADV_UNI_FRAG_HEAD = BIT(0),
BATADV_UNI_FRAG_LARGETAIL = BIT(1), BATADV_UNI_FRAG_LARGETAIL = BIT(1),
}; };
/* TT_QUERY subtypes */ /* tt data subtypes */
#define BATADV_TT_QUERY_TYPE_MASK 0x3 #define BATADV_TT_DATA_TYPE_MASK 0x0F
enum batadv_tt_query_packettype {
BATADV_TT_REQUEST = 0,
BATADV_TT_RESPONSE = 1,
};
/* TT_QUERY flags */ /**
enum batadv_tt_query_flags { * enum batadv_tt_data_flags - flags for tt data tvlv
BATADV_TT_FULL_TABLE = BIT(2), * @BATADV_TT_OGM_DIFF: TT diff propagated through OGM
* @BATADV_TT_REQUEST: TT request message
* @BATADV_TT_RESPONSE: TT response message
* @BATADV_TT_FULL_TABLE: contains full table to replace existing table
*/
enum batadv_tt_data_flags {
BATADV_TT_OGM_DIFF = BIT(0),
BATADV_TT_REQUEST = BIT(1),
BATADV_TT_RESPONSE = BIT(2),
BATADV_TT_FULL_TABLE = BIT(4),
}; };
/* BATADV_TT_CLIENT flags. /* BATADV_TT_CLIENT flags.
...@@ -99,10 +122,10 @@ enum batadv_tt_client_flags { ...@@ -99,10 +122,10 @@ enum batadv_tt_client_flags {
BATADV_TT_CLIENT_DEL = BIT(0), BATADV_TT_CLIENT_DEL = BIT(0),
BATADV_TT_CLIENT_ROAM = BIT(1), BATADV_TT_CLIENT_ROAM = BIT(1),
BATADV_TT_CLIENT_WIFI = BIT(2), BATADV_TT_CLIENT_WIFI = BIT(2),
BATADV_TT_CLIENT_TEMP = BIT(3),
BATADV_TT_CLIENT_NOPURGE = BIT(8), BATADV_TT_CLIENT_NOPURGE = BIT(8),
BATADV_TT_CLIENT_NEW = BIT(9), BATADV_TT_CLIENT_NEW = BIT(9),
BATADV_TT_CLIENT_PENDING = BIT(10), BATADV_TT_CLIENT_PENDING = BIT(10),
BATADV_TT_CLIENT_TEMP = BIT(11),
}; };
/* claim frame types for the bridge loop avoidance */ /* claim frame types for the bridge loop avoidance */
...@@ -113,6 +136,22 @@ enum batadv_bla_claimframe { ...@@ -113,6 +136,22 @@ enum batadv_bla_claimframe {
BATADV_CLAIM_TYPE_REQUEST = 0x03, BATADV_CLAIM_TYPE_REQUEST = 0x03,
}; };
/**
* enum batadv_tvlv_type - tvlv type definitions
* @BATADV_TVLV_GW: gateway tvlv
* @BATADV_TVLV_DAT: distributed arp table tvlv
* @BATADV_TVLV_NC: network coding tvlv
* @BATADV_TVLV_TT: translation table tvlv
* @BATADV_TVLV_ROAM: roaming advertisement tvlv
*/
enum batadv_tvlv_type {
BATADV_TVLV_GW = 0x01,
BATADV_TVLV_DAT = 0x02,
BATADV_TVLV_NC = 0x03,
BATADV_TVLV_TT = 0x04,
BATADV_TVLV_ROAM = 0x05,
};
/* the destination hardware field in the ARP frame is used to /* the destination hardware field in the ARP frame is used to
* transport the claim type and the group id * transport the claim type and the group id
*/ */
...@@ -131,18 +170,25 @@ struct batadv_header { ...@@ -131,18 +170,25 @@ struct batadv_header {
*/ */
}; };
/**
* struct batadv_ogm_packet - ogm (routing protocol) packet
* @header: common batman packet header
* @flags: contains routing relevant flags - see enum batadv_iv_flags
* @tvlv_len: length of tvlv data following the ogm header
*/
struct batadv_ogm_packet { struct batadv_ogm_packet {
struct batadv_header header; struct batadv_header header;
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ uint8_t flags;
__be32 seqno; __be32 seqno;
uint8_t orig[ETH_ALEN]; uint8_t orig[ETH_ALEN];
uint8_t prev_sender[ETH_ALEN]; uint8_t prev_sender[ETH_ALEN];
uint8_t gw_flags; /* flags related to gateway class */ uint8_t reserved;
uint8_t tq; uint8_t tq;
uint8_t tt_num_changes; __be16 tvlv_len;
uint8_t ttvn; /* translation table version number */ /* __packed is not needed as the struct size is divisible by 4,
__be16 tt_crc; * and the largest data type in this struct has a size of 4.
} __packed; */
};
#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
...@@ -231,54 +277,6 @@ struct batadv_bcast_packet { ...@@ -231,54 +277,6 @@ struct batadv_bcast_packet {
#pragma pack() #pragma pack()
struct batadv_vis_packet {
struct batadv_header header;
uint8_t vis_type; /* which type of vis-participant sent this? */
__be32 seqno; /* sequence number */
uint8_t entries; /* number of entries behind this struct */
uint8_t reserved;
uint8_t vis_orig[ETH_ALEN]; /* originator reporting its neighbors */
uint8_t target_orig[ETH_ALEN]; /* who should receive this packet */
uint8_t sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
};
struct batadv_tt_query_packet {
struct batadv_header header;
/* the flag field is a combination of:
* - TT_REQUEST or TT_RESPONSE
* - TT_FULL_TABLE
*/
uint8_t flags;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN];
/* the ttvn field is:
* if TT_REQUEST: ttvn that triggered the
* request
* if TT_RESPONSE: new ttvn for the src
* orig_node
*/
uint8_t ttvn;
/* tt_data field is:
* if TT_REQUEST: crc associated with the
* ttvn
* if TT_RESPONSE: table_size
*/
__be16 tt_data;
} __packed;
struct batadv_roam_adv_packet {
struct batadv_header header;
uint8_t reserved;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN];
uint8_t client[ETH_ALEN];
} __packed;
struct batadv_tt_change {
uint8_t flags;
uint8_t addr[ETH_ALEN];
} __packed;
/** /**
* struct batadv_coded_packet - network coded packet * struct batadv_coded_packet - network coded packet
* @header: common batman packet header and ttl of first included packet * @header: common batman packet header and ttl of first included packet
...@@ -311,4 +309,82 @@ struct batadv_coded_packet { ...@@ -311,4 +309,82 @@ struct batadv_coded_packet {
__be16 coded_len; __be16 coded_len;
}; };
/**
* struct batadv_unicast_tvlv - generic unicast packet with tvlv payload
* @header: common batman packet header
* @reserved: reserved field (for packet alignment)
* @src: address of the source
* @dst: address of the destination
* @tvlv_len: length of tvlv data following the unicast tvlv header
* @align: 2 bytes to align the header to a 4 byte boundry
*/
struct batadv_unicast_tvlv_packet {
struct batadv_header header;
uint8_t reserved;
uint8_t dst[ETH_ALEN];
uint8_t src[ETH_ALEN];
__be16 tvlv_len;
uint16_t align;
};
/**
* struct batadv_tvlv_hdr - base tvlv header struct
* @type: tvlv container type (see batadv_tvlv_type)
* @version: tvlv container version
* @len: tvlv container length
*/
struct batadv_tvlv_hdr {
uint8_t type;
uint8_t version;
__be16 len;
};
/**
* struct batadv_tvlv_gateway_data - gateway data propagated through gw tvlv
* container
* @bandwidth_down: advertised uplink download bandwidth
* @bandwidth_up: advertised uplink upload bandwidth
*/
struct batadv_tvlv_gateway_data {
__be32 bandwidth_down;
__be32 bandwidth_up;
};
/**
* struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
* @flags: translation table flags (see batadv_tt_data_flags)
* @ttvn: translation table version number
* @reserved: field reserved for future use
* @crc: crc32 checksum of the local translation table
*/
struct batadv_tvlv_tt_data {
uint8_t flags;
uint8_t ttvn;
uint16_t reserved;
__be32 crc;
};
/**
* struct batadv_tvlv_tt_change - translation table diff data
* @flags: status indicators concerning the non-mesh client (see
* batadv_tt_client_flags)
* @reserved: reserved field
* @addr: mac address of non-mesh client that triggered this tt change
*/
struct batadv_tvlv_tt_change {
uint8_t flags;
uint8_t reserved;
uint8_t addr[ETH_ALEN];
};
/**
* struct batadv_tvlv_roam_adv - roaming advertisement
* @client: mac address of roaming client
* @reserved: field reserved for future use
*/
struct batadv_tvlv_roam_adv {
uint8_t client[ETH_ALEN];
uint16_t reserved;
};
#endif /* _NET_BATMAN_ADV_PACKET_H_ */ #endif /* _NET_BATMAN_ADV_PACKET_H_ */
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "icmp_socket.h" #include "icmp_socket.h"
#include "translation-table.h" #include "translation-table.h"
#include "originator.h" #include "originator.h"
#include "vis.h"
#include "unicast.h" #include "unicast.h"
#include "bridge_loop_avoidance.h" #include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h" #include "distributed-arp-table.h"
...@@ -557,126 +556,6 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, ...@@ -557,126 +556,6 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
return 0; return 0;
} }
int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_tt_query_packet *tt_query;
uint16_t tt_size;
int hdr_size = sizeof(*tt_query);
char tt_flag;
size_t packet_size;
if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;
/* I could need to modify it */
if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0)
goto out;
tt_query = (struct batadv_tt_query_packet *)skb->data;
switch (tt_query->flags & BATADV_TT_QUERY_TYPE_MASK) {
case BATADV_TT_REQUEST:
batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_RX);
/* If we cannot provide an answer the tt_request is
* forwarded
*/
if (!batadv_send_tt_response(bat_priv, tt_query)) {
if (tt_query->flags & BATADV_TT_FULL_TABLE)
tt_flag = 'F';
else
tt_flag = '.';
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Routing TT_REQUEST to %pM [%c]\n",
tt_query->dst,
tt_flag);
return batadv_route_unicast_packet(skb, recv_if);
}
break;
case BATADV_TT_RESPONSE:
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
if (batadv_is_my_mac(bat_priv, tt_query->dst)) {
/* packet needs to be linearized to access the TT
* changes
*/
if (skb_linearize(skb) < 0)
goto out;
/* skb_linearize() possibly changed skb->data */
tt_query = (struct batadv_tt_query_packet *)skb->data;
tt_size = batadv_tt_len(ntohs(tt_query->tt_data));
/* Ensure we have all the claimed data */
packet_size = sizeof(struct batadv_tt_query_packet);
packet_size += tt_size;
if (unlikely(skb_headlen(skb) < packet_size))
goto out;
batadv_handle_tt_response(bat_priv, tt_query);
} else {
if (tt_query->flags & BATADV_TT_FULL_TABLE)
tt_flag = 'F';
else
tt_flag = '.';
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Routing TT_RESPONSE to %pM [%c]\n",
tt_query->dst,
tt_flag);
return batadv_route_unicast_packet(skb, recv_if);
}
break;
}
out:
/* returning NET_RX_DROP will make the caller function kfree the skb */
return NET_RX_DROP;
}
int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_roam_adv_packet *roam_adv_packet;
struct batadv_orig_node *orig_node;
if (batadv_check_unicast_packet(bat_priv, skb,
sizeof(*roam_adv_packet)) < 0)
goto out;
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
roam_adv_packet = (struct batadv_roam_adv_packet *)skb->data;
if (!batadv_is_my_mac(bat_priv, roam_adv_packet->dst))
return batadv_route_unicast_packet(skb, recv_if);
/* check if it is a backbone gateway. we don't accept
* roaming advertisement from it, as it has the same
* entries as we have.
*/
if (batadv_bla_is_backbone_gw_orig(bat_priv, roam_adv_packet->src))
goto out;
orig_node = batadv_orig_hash_find(bat_priv, roam_adv_packet->src);
if (!orig_node)
goto out;
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Received ROAMING_ADV from %pM (client %pM)\n",
roam_adv_packet->src, roam_adv_packet->client);
batadv_tt_global_add(bat_priv, orig_node, roam_adv_packet->client,
BATADV_TT_CLIENT_ROAM,
atomic_read(&orig_node->last_ttvn) + 1);
batadv_orig_node_free_ref(orig_node);
out:
/* returning NET_RX_DROP will make the caller function kfree the skb */
return NET_RX_DROP;
}
/* find a suitable router for this originator, and use /* find a suitable router for this originator, and use
* bonding if possible. increases the found neighbors * bonding if possible. increases the found neighbors
* refcount. * refcount.
...@@ -1032,6 +911,34 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, ...@@ -1032,6 +911,34 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
return 1; return 1;
} }
/**
* batadv_recv_unhandled_unicast_packet - receive and process packets which
* are in the unicast number space but not yet known to the implementation
* @skb: unicast tvlv packet to process
* @recv_if: pointer to interface this packet was received on
*
* Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
* otherwise.
*/
int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
struct batadv_unicast_packet *unicast_packet;
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
int check, hdr_size = sizeof(*unicast_packet);
check = batadv_check_unicast_packet(bat_priv, skb, hdr_size);
if (check < 0)
return NET_RX_DROP;
/* we don't know about this type, drop it. */
unicast_packet = (struct batadv_unicast_packet *)skb->data;
if (batadv_is_my_mac(bat_priv, unicast_packet->dest))
return NET_RX_DROP;
return batadv_route_unicast_packet(skb, recv_if);
}
int batadv_recv_unicast_packet(struct sk_buff *skb, int batadv_recv_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if) struct batadv_hard_iface *recv_if)
{ {
...@@ -1139,6 +1046,54 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, ...@@ -1139,6 +1046,54 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
return batadv_route_unicast_packet(skb, recv_if); return batadv_route_unicast_packet(skb, recv_if);
} }
/**
* batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
* @skb: unicast tvlv packet to process
* @recv_if: pointer to interface this packet was received on
* @dst_addr: the payload destination
*
* Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP
* otherwise.
*/
int batadv_recv_unicast_tvlv(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_unicast_tvlv_packet *unicast_tvlv_packet;
unsigned char *tvlv_buff;
uint16_t tvlv_buff_len;
int hdr_size = sizeof(*unicast_tvlv_packet);
int ret = NET_RX_DROP;
if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;
/* the header is likely to be modified while forwarding */
if (skb_cow(skb, hdr_size) < 0)
return NET_RX_DROP;
/* packet needs to be linearized to access the tvlv content */
if (skb_linearize(skb) < 0)
return NET_RX_DROP;
unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data;
tvlv_buff = (unsigned char *)(skb->data + hdr_size);
tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len);
if (tvlv_buff_len > skb->len - hdr_size)
return NET_RX_DROP;
ret = batadv_tvlv_containers_process(bat_priv, false, NULL,
unicast_tvlv_packet->src,
unicast_tvlv_packet->dst,
tvlv_buff, tvlv_buff_len);
if (ret != NET_RX_SUCCESS)
ret = batadv_route_unicast_packet(skb, recv_if);
return ret;
}
int batadv_recv_bcast_packet(struct sk_buff *skb, int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if) struct batadv_hard_iface *recv_if)
...@@ -1240,53 +1195,3 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, ...@@ -1240,53 +1195,3 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
batadv_orig_node_free_ref(orig_node); batadv_orig_node_free_ref(orig_node);
return ret; return ret;
} }
int batadv_recv_vis_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
struct batadv_vis_packet *vis_packet;
struct ethhdr *ethhdr;
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
int hdr_size = sizeof(*vis_packet);
/* keep skb linear */
if (skb_linearize(skb) < 0)
return NET_RX_DROP;
if (unlikely(!pskb_may_pull(skb, hdr_size)))
return NET_RX_DROP;
vis_packet = (struct batadv_vis_packet *)skb->data;
ethhdr = eth_hdr(skb);
/* not for me */
if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
return NET_RX_DROP;
/* ignore own packets */
if (batadv_is_my_mac(bat_priv, vis_packet->vis_orig))
return NET_RX_DROP;
if (batadv_is_my_mac(bat_priv, vis_packet->sender_orig))
return NET_RX_DROP;
switch (vis_packet->vis_type) {
case BATADV_VIS_TYPE_SERVER_SYNC:
batadv_receive_server_sync_packet(bat_priv, vis_packet,
skb_headlen(skb));
break;
case BATADV_VIS_TYPE_CLIENT_UPDATE:
batadv_receive_client_update_packet(bat_priv, vis_packet,
skb_headlen(skb));
break;
default: /* ignore unknown packet */
break;
}
/* We take a copy of the data in the packet, so we should
* always free the skbuf.
*/
return NET_RX_DROP;
}
...@@ -34,12 +34,14 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, ...@@ -34,12 +34,14 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
int batadv_recv_bcast_packet(struct sk_buff *skb, int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
int batadv_recv_vis_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_tt_query(struct sk_buff *skb, int batadv_recv_tt_query(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
int batadv_recv_roam_adv(struct sk_buff *skb, int batadv_recv_roam_adv(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
int batadv_recv_unicast_tvlv(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
struct batadv_neigh_node * struct batadv_neigh_node *
batadv_find_router(struct batadv_priv *bat_priv, batadv_find_router(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_node,
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "translation-table.h" #include "translation-table.h"
#include "soft-interface.h" #include "soft-interface.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "vis.h"
#include "gateway_common.h" #include "gateway_common.h"
#include "originator.h" #include "originator.h"
#include "network-coding.h" #include "network-coding.h"
......
...@@ -469,10 +469,10 @@ static int batadv_softif_init_late(struct net_device *dev) ...@@ -469,10 +469,10 @@ static int batadv_softif_init_late(struct net_device *dev)
atomic_set(&bat_priv->distributed_arp_table, 1); atomic_set(&bat_priv->distributed_arp_table, 1);
#endif #endif
atomic_set(&bat_priv->ap_isolation, 0); atomic_set(&bat_priv->ap_isolation, 0);
atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw_sel_class, 20); atomic_set(&bat_priv->gw_sel_class, 20);
atomic_set(&bat_priv->gw_bandwidth, 41); atomic_set(&bat_priv->gw.bandwidth_down, 100);
atomic_set(&bat_priv->gw.bandwidth_up, 20);
atomic_set(&bat_priv->orig_interval, 1000); atomic_set(&bat_priv->orig_interval, 1000);
atomic_set(&bat_priv->hop_penalty, 30); atomic_set(&bat_priv->hop_penalty, 30);
#ifdef CONFIG_BATMAN_ADV_DEBUG #ifdef CONFIG_BATMAN_ADV_DEBUG
......
...@@ -21,11 +21,11 @@ ...@@ -21,11 +21,11 @@
#include "sysfs.h" #include "sysfs.h"
#include "translation-table.h" #include "translation-table.h"
#include "distributed-arp-table.h" #include "distributed-arp-table.h"
#include "network-coding.h"
#include "originator.h" #include "originator.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "gateway_common.h" #include "gateway_common.h"
#include "gateway_client.h" #include "gateway_client.h"
#include "vis.h"
static struct net_device *batadv_kobj_to_netdev(struct kobject *obj) static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
{ {
...@@ -230,74 +230,6 @@ __batadv_store_uint_attr(const char *buff, size_t count, ...@@ -230,74 +230,6 @@ __batadv_store_uint_attr(const char *buff, size_t count,
return ret; return ret;
} }
static ssize_t batadv_show_vis_mode(struct kobject *kobj,
struct attribute *attr, char *buff)
{
struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
int vis_mode = atomic_read(&bat_priv->vis_mode);
const char *mode;
if (vis_mode == BATADV_VIS_TYPE_CLIENT_UPDATE)
mode = "client";
else
mode = "server";
return sprintf(buff, "%s\n", mode);
}
static ssize_t batadv_store_vis_mode(struct kobject *kobj,
struct attribute *attr, char *buff,
size_t count)
{
struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
struct batadv_priv *bat_priv = netdev_priv(net_dev);
unsigned long val;
int ret, vis_mode_tmp = -1;
const char *old_mode, *new_mode;
ret = kstrtoul(buff, 10, &val);
if (((count == 2) && (!ret) &&
(val == BATADV_VIS_TYPE_CLIENT_UPDATE)) ||
(strncmp(buff, "client", 6) == 0) ||
(strncmp(buff, "off", 3) == 0))
vis_mode_tmp = BATADV_VIS_TYPE_CLIENT_UPDATE;
if (((count == 2) && (!ret) &&
(val == BATADV_VIS_TYPE_SERVER_SYNC)) ||
(strncmp(buff, "server", 6) == 0))
vis_mode_tmp = BATADV_VIS_TYPE_SERVER_SYNC;
if (vis_mode_tmp < 0) {
if (buff[count - 1] == '\n')
buff[count - 1] = '\0';
batadv_info(net_dev,
"Invalid parameter for 'vis mode' setting received: %s\n",
buff);
return -EINVAL;
}
if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
return count;
if (atomic_read(&bat_priv->vis_mode) == BATADV_VIS_TYPE_CLIENT_UPDATE)
old_mode = "client";
else
old_mode = "server";
if (vis_mode_tmp == BATADV_VIS_TYPE_CLIENT_UPDATE)
new_mode = "client";
else
new_mode = "server";
batadv_info(net_dev, "Changing vis mode from: %s to: %s\n", old_mode,
new_mode);
atomic_set(&bat_priv->vis_mode, (unsigned int)vis_mode_tmp);
return count;
}
static ssize_t batadv_show_bat_algo(struct kobject *kobj, static ssize_t batadv_show_bat_algo(struct kobject *kobj,
struct attribute *attr, char *buff) struct attribute *attr, char *buff)
{ {
...@@ -390,6 +322,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj, ...@@ -390,6 +322,7 @@ static ssize_t batadv_store_gw_mode(struct kobject *kobj,
*/ */
batadv_gw_check_client_stop(bat_priv); batadv_gw_check_client_stop(bat_priv);
atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp); atomic_set(&bat_priv->gw_mode, (unsigned int)gw_mode_tmp);
batadv_gw_tvlv_container_update(bat_priv);
return count; return count;
} }
...@@ -397,15 +330,13 @@ static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, ...@@ -397,15 +330,13 @@ static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
struct attribute *attr, char *buff) struct attribute *attr, char *buff)
{ {
struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj); struct batadv_priv *bat_priv = batadv_kobj_to_batpriv(kobj);
int down, up; uint32_t down, up;
int gw_bandwidth = atomic_read(&bat_priv->gw_bandwidth);
down = atomic_read(&bat_priv->gw.bandwidth_down);
batadv_gw_bandwidth_to_kbit(gw_bandwidth, &down, &up); up = atomic_read(&bat_priv->gw.bandwidth_up);
return sprintf(buff, "%i%s/%i%s\n",
(down > 2048 ? down / 1024 : down), return sprintf(buff, "%u.%u/%u.%u MBit\n", down / 10,
(down > 2048 ? "MBit" : "KBit"), down % 10, up / 10, up % 10);
(up > 2048 ? up / 1024 : up),
(up > 2048 ? "MBit" : "KBit"));
} }
static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, static ssize_t batadv_store_gw_bwidth(struct kobject *kobj,
...@@ -426,12 +357,11 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); ...@@ -426,12 +357,11 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
#endif #endif
#ifdef CONFIG_BATMAN_ADV_DAT #ifdef CONFIG_BATMAN_ADV_DAT
BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL); BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR,
batadv_dat_status_update);
#endif #endif
BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu); BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
batadv_store_vis_mode);
static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL); static BATADV_ATTR(routing_algo, S_IRUGO, batadv_show_bat_algo, NULL);
static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode, static BATADV_ATTR(gw_mode, S_IRUGO | S_IWUSR, batadv_show_gw_mode,
batadv_store_gw_mode); batadv_store_gw_mode);
...@@ -447,7 +377,8 @@ static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, ...@@ -447,7 +377,8 @@ static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth,
BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL);
#endif #endif
#ifdef CONFIG_BATMAN_ADV_NC #ifdef CONFIG_BATMAN_ADV_NC
BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR, NULL); BATADV_ATTR_SIF_BOOL(network_coding, S_IRUGO | S_IWUSR,
batadv_nc_status_update);
#endif #endif
static struct batadv_attribute *batadv_mesh_attrs[] = { static struct batadv_attribute *batadv_mesh_attrs[] = {
...@@ -461,7 +392,6 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { ...@@ -461,7 +392,6 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
#endif #endif
&batadv_attr_fragmentation, &batadv_attr_fragmentation,
&batadv_attr_ap_isolation, &batadv_attr_ap_isolation,
&batadv_attr_vis_mode,
&batadv_attr_routing_algo, &batadv_attr_routing_algo,
&batadv_attr_gw_mode, &batadv_attr_gw_mode,
&batadv_attr_orig_interval, &batadv_attr_orig_interval,
......
This diff is collapsed.
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
int batadv_tt_len(int changes_num);
int batadv_tt_init(struct batadv_priv *bat_priv); int batadv_tt_init(struct batadv_priv *bat_priv);
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
int ifindex); int ifindex);
...@@ -43,20 +42,10 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, ...@@ -43,20 +42,10 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
const uint8_t *src, const uint8_t *src,
const uint8_t *addr); const uint8_t *addr);
void batadv_tt_free(struct batadv_priv *bat_priv); void batadv_tt_free(struct batadv_priv *bat_priv);
bool batadv_send_tt_response(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_request);
bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr); bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr);
void batadv_handle_tt_response(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_response);
bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src, bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
uint8_t *dst); uint8_t *dst);
void batadv_tt_update_orig(struct batadv_priv *bat_priv, void batadv_tt_local_commit_changes(struct batadv_priv *bat_priv);
struct batadv_orig_node *orig_node,
const unsigned char *tt_buff, uint8_t tt_num_changes,
uint8_t ttvn, uint16_t tt_crc);
int batadv_tt_append_diff(struct batadv_priv *bat_priv,
unsigned char **packet_buff, int *packet_buff_len,
int packet_min_len);
bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
uint8_t *addr); uint8_t *addr);
bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv, bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
......
This diff is collapsed.
This diff is collapsed.
/* Copyright (C) 2008-2013 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*/
#ifndef _NET_BATMAN_ADV_VIS_H_
#define _NET_BATMAN_ADV_VIS_H_
/* timeout of vis packets in milliseconds */
#define BATADV_VIS_TIMEOUT 200000
int batadv_vis_seq_print_text(struct seq_file *seq, void *offset);
void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv,
struct batadv_vis_packet *vis_packet,
int vis_info_len);
void batadv_receive_client_update_packet(struct batadv_priv *bat_priv,
struct batadv_vis_packet *vis_packet,
int vis_info_len);
int batadv_vis_init(struct batadv_priv *bat_priv);
void batadv_vis_quit(struct batadv_priv *bat_priv);
#endif /* _NET_BATMAN_ADV_VIS_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment