Skip to content

Commit

Permalink
batman-adv: add the VLAN ID attribute to the TT entry
Browse files Browse the repository at this point in the history
To make the translation table code VLAN-aware, each entry
must carry the VLAN ID which it belongs to. This patch adds
such attribute to the related TT structures.

Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
  • Loading branch information
Antonio Quartulli authored and Antonio Quartulli committed Oct 19, 2013
1 parent bc58eee commit c018ad3
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 135 deletions.
35 changes: 11 additions & 24 deletions net/batman-adv/bridge_loop_avoidance.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,27 +858,25 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if,
struct sk_buff *skb)
{
struct ethhdr *ethhdr;
struct batadv_bla_claim_dst *bla_dst;
uint8_t *hw_src, *hw_dst;
struct vlan_ethhdr *vhdr;
struct ethhdr *ethhdr;
struct arphdr *arphdr;
uint8_t *hw_src, *hw_dst;
struct batadv_bla_claim_dst *bla_dst;
unsigned short vid;
__be16 proto;
int headlen;
unsigned short vid = BATADV_NO_FLAGS;
int ret;

vid = batadv_get_vid(skb, 0);
ethhdr = eth_hdr(skb);

if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
proto = ethhdr->h_proto;
headlen = ETH_HLEN;
if (vid & BATADV_VLAN_HAS_TAG) {
vhdr = (struct vlan_ethhdr *)ethhdr;
vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
vid |= BATADV_VLAN_HAS_TAG;
proto = vhdr->h_vlan_encapsulated_proto;
headlen = sizeof(*vhdr);
} else {
proto = ethhdr->h_proto;
headlen = ETH_HLEN;
headlen += VLAN_HLEN;
}

if (proto != htons(ETH_P_ARP))
Expand Down Expand Up @@ -1365,10 +1363,8 @@ int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig)
int batadv_bla_is_backbone_gw(struct sk_buff *skb,
struct batadv_orig_node *orig_node, int hdr_size)
{
struct ethhdr *ethhdr;
struct vlan_ethhdr *vhdr;
struct batadv_bla_backbone_gw *backbone_gw;
unsigned short vid = BATADV_NO_FLAGS;
unsigned short vid;

if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
return 0;
Expand All @@ -1377,16 +1373,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
return 0;

ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size);

if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
if (!pskb_may_pull(skb, hdr_size + VLAN_ETH_HLEN))
return 0;

vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
vid |= BATADV_VLAN_HAS_TAG;
}
vid = batadv_get_vid(skb, hdr_size);

/* see if this originator is a backbone gw for this VLAN */
backbone_gw = batadv_backbone_hash_find(orig_node->bat_priv,
Expand Down
11 changes: 7 additions & 4 deletions net/batman-adv/distributed-arp-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,8 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
* additional DAT answer may trigger kernel warnings about
* a packet coming from the wrong port.
*/
if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) {
if (batadv_is_my_client(bat_priv, dat_entry->mac_addr,
BATADV_NO_FLAGS)) {
ret = true;
goto out;
}
Expand Down Expand Up @@ -990,9 +991,11 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
*/
if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
err = batadv_send_skb_unicast_4addr(bat_priv, skb_new,
BATADV_P_DAT_CACHE_REPLY);
BATADV_P_DAT_CACHE_REPLY,
BATADV_NO_FLAGS);
else
err = batadv_send_skb_unicast(bat_priv, skb_new);
err = batadv_send_skb_unicast(bat_priv, skb_new,
BATADV_NO_FLAGS);

if (!err) {
batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
Expand Down Expand Up @@ -1080,7 +1083,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
/* if this REPLY is directed to a client of mine, let's deliver the
* packet to the interface
*/
ret = !batadv_is_my_client(bat_priv, hw_dst);
ret = !batadv_is_my_client(bat_priv, hw_dst, BATADV_NO_FLAGS);
out:
if (ret)
kfree_skb(skb);
Expand Down
3 changes: 2 additions & 1 deletion net/batman-adv/gateway_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,8 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,

ethhdr = (struct ethhdr *)skb->data;
orig_dst_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
ethhdr->h_dest);
ethhdr->h_dest,
BATADV_NO_FLAGS);
if (!orig_dst_node)
goto out;

Expand Down
29 changes: 28 additions & 1 deletion net/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
goto err;

batadv_tt_local_add(soft_iface, soft_iface->dev_addr,
BATADV_NULL_IFINDEX);
BATADV_NO_FLAGS, BATADV_NULL_IFINDEX);

ret = batadv_bla_init(bat_priv);
if (ret < 0)
Expand Down Expand Up @@ -1144,6 +1144,33 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
batadv_orig_node_free_ref(orig_node);
}

/**
* batadv_get_vid - extract the VLAN identifier from skb if any
* @skb: the buffer containing the packet
* @header_len: length of the batman header preceding the ethernet header
*
* If the packet embedded in the skb is vlan tagged this function returns the
* VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned.
*/
unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len)
{
struct ethhdr *ethhdr = (struct ethhdr *)(skb->data + header_len);
struct vlan_ethhdr *vhdr;
unsigned short vid;

if (ethhdr->h_proto != htons(ETH_P_8021Q))
return BATADV_NO_FLAGS;

if (!pskb_may_pull(skb, header_len + VLAN_ETH_HLEN))
return BATADV_NO_FLAGS;

vhdr = (struct vlan_ethhdr *)(skb->data + header_len);
vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
vid |= BATADV_VLAN_HAS_TAG;

return vid;
}

static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
{
struct batadv_algo_ops *bat_algo_ops;
Expand Down
9 changes: 1 addition & 8 deletions net/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,6 @@ enum batadv_uev_type {
#include <linux/seq_file.h>
#include "types.h"

/**
* batadv_vlan_flags - flags for the four MSB of any vlan ID field
* @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
*/
enum batadv_vlan_flags {
BATADV_VLAN_HAS_TAG = BIT(15),
};

#define BATADV_PRINT_VID(vid) (vid & BATADV_VLAN_HAS_TAG ? \
(int)(vid & VLAN_VID_MASK) : -1)

Expand Down Expand Up @@ -368,5 +360,6 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,
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);
unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len);

#endif /* _NET_BATMAN_ADV_MAIN_H_ */
14 changes: 12 additions & 2 deletions net/batman-adv/packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ enum batadv_tt_client_flags {
BATADV_TT_CLIENT_TEMP = BIT(11),
};

/**
* batadv_vlan_flags - flags for the four MSB of any vlan ID field
* @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not
*/
enum batadv_vlan_flags {
BATADV_VLAN_HAS_TAG = BIT(15),
};

/* claim frame types for the bridge loop avoidance */
enum batadv_bla_claimframe {
BATADV_CLAIM_TYPE_CLAIM = 0x00,
Expand Down Expand Up @@ -399,21 +407,23 @@ struct batadv_tvlv_tt_data {
* batadv_tt_client_flags)
* @reserved: reserved field
* @addr: mac address of non-mesh client that triggered this tt change
* @vid: VLAN identifier
*/
struct batadv_tvlv_tt_change {
uint8_t flags;
uint8_t reserved;
uint8_t addr[ETH_ALEN];
__be16 vid;
};

/**
* struct batadv_tvlv_roam_adv - roaming advertisement
* @client: mac address of roaming client
* @reserved: field reserved for future use
* @vid: VLAN identifier
*/
struct batadv_tvlv_roam_adv {
uint8_t client[ETH_ALEN];
uint16_t reserved;
__be16 vid;
};

#endif /* _NET_BATMAN_ADV_PACKET_H_ */
26 changes: 16 additions & 10 deletions net/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "network-coding.h"
#include "fragmentation.h"

#include <linux/if_vlan.h>

static int batadv_route_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);

Expand Down Expand Up @@ -724,6 +726,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
* @bat_priv: the bat priv with all the soft interface information
* @unicast_packet: the unicast header to be updated
* @dst_addr: the payload destination
* @vid: VLAN identifier
*
* Search the translation table for dst_addr and update the unicast header with
* the new corresponding information (originator address where the destination
Expand All @@ -734,21 +737,22 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
static bool
batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
struct batadv_unicast_packet *unicast_packet,
uint8_t *dst_addr)
uint8_t *dst_addr, unsigned short vid)
{
struct batadv_orig_node *orig_node = NULL;
struct batadv_hard_iface *primary_if = NULL;
bool ret = false;
uint8_t *orig_addr, orig_ttvn;

if (batadv_is_my_client(bat_priv, dst_addr)) {
if (batadv_is_my_client(bat_priv, dst_addr, vid)) {
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
goto out;
orig_addr = primary_if->net_dev->dev_addr;
orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
} else {
orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr);
orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr,
vid);
if (!orig_node)
goto out;

Expand All @@ -775,11 +779,12 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,

static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_len) {
uint8_t curr_ttvn, old_ttvn;
struct batadv_unicast_packet *unicast_packet;
struct batadv_hard_iface *primary_if;
struct batadv_orig_node *orig_node;
uint8_t curr_ttvn, old_ttvn;
struct ethhdr *ethhdr;
struct batadv_hard_iface *primary_if;
struct batadv_unicast_packet *unicast_packet;
unsigned short vid;
int is_old_ttvn;

/* check if there is enough data before accessing it */
Expand All @@ -791,16 +796,17 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
return 0;

unicast_packet = (struct batadv_unicast_packet *)skb->data;
vid = batadv_get_vid(skb, hdr_len);
ethhdr = (struct ethhdr *)(skb->data + hdr_len);

/* check if the destination client was served by this node and it is now
* roaming. In this case, it means that the node has got a ROAM_ADV
* message and that it knows the new destination in the mesh to re-route
* the packet to
*/
if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) {
if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) {
if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
ethhdr->h_dest))
ethhdr->h_dest, vid))
net_ratelimited_function(batadv_dbg, BATADV_DBG_TT,
bat_priv,
"Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n",
Expand Down Expand Up @@ -846,7 +852,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
* target host
*/
if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
ethhdr->h_dest)) {
ethhdr->h_dest, vid)) {
net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
"Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n",
unicast_packet->dest, ethhdr->h_dest,
Expand All @@ -858,7 +864,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
* currently served by this node or there is no destination at all and
* it is possible to drop the packet
*/
if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
if (!batadv_is_my_client(bat_priv, ethhdr->h_dest, vid))
return 0;

/* update the header in order to let the packet be delivered to this
Expand Down
8 changes: 5 additions & 3 deletions net/batman-adv/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,14 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
* @packet_type: the batman unicast packet type to use
* @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
* 4addr packets)
* @vid: the vid to be used to search the translation table
*
* Returns 1 in case of error or 0 otherwise.
*/
int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
struct sk_buff *skb, int packet_type,
int packet_subtype)
int packet_subtype,
unsigned short vid)
{
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct batadv_unicast_packet *unicast_packet;
Expand All @@ -260,7 +262,7 @@ int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
* returns NULL in case of AP isolation
*/
orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
ethhdr->h_dest);
ethhdr->h_dest, vid);

if (!orig_node)
goto out;
Expand Down Expand Up @@ -290,7 +292,7 @@ int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
* try to reroute it because the ttvn contained in the header is less
* than the current one
*/
if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest))
if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
unicast_packet->ttvn = unicast_packet->ttvn - 1;

if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
Expand Down
16 changes: 10 additions & 6 deletions net/batman-adv/send.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,23 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
int packet_subtype);
int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
struct sk_buff *skb, int packet_type,
int packet_subtype);

int packet_subtype,
unsigned short vid);

/**
* batadv_send_unicast_skb - send the skb encapsulated in a unicast packet
* @bat_priv: the bat priv with all the soft interface information
* @skb: the payload to send
* @vid: the vid to be used to search the translation table
*
* Returns 1 in case of error or 0 otherwise.
*/
static inline int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
struct sk_buff *skb)
struct sk_buff *skb,
unsigned short vid)
{
return batadv_send_skb_generic_unicast(bat_priv, skb, BATADV_UNICAST,
0);
0, vid);
}

/**
Expand All @@ -63,16 +65,18 @@ static inline int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
* @bat_priv: the bat priv with all the soft interface information
* @skb: the payload to send
* @packet_subtype: the unicast 4addr packet subtype to use
* @vid: the vid to be used to search the translation table
*
* Returns 1 in case of error or 0 otherwise.
*/
static inline int batadv_send_skb_unicast_4addr(struct batadv_priv *bat_priv,
struct sk_buff *skb,
int packet_subtype)
int packet_subtype,
unsigned short vid)
{
return batadv_send_skb_generic_unicast(bat_priv, skb,
BATADV_UNICAST_4ADDR,
packet_subtype);
packet_subtype, vid);
}

#endif /* _NET_BATMAN_ADV_SEND_H_ */
Loading

0 comments on commit c018ad3

Please sign in to comment.