Commit 303597e4 authored by David S. Miller's avatar David S. Miller

Merge tag 'batadv-next-pullrequest-20210608' of git://git.open-mesh.org/linux-merge

Simon Wunderlich says:

====================
pull request for net-next: batman-adv 2021-06-08

here is a feature/cleanup pull request of batman-adv to go into net-next.

Please pull or let me know of any problem!

This feature/cleanup patchset includes the following patches:

 - bump version strings, by Simon Wunderlich

 - consistently send iface index/name in genlmsg, by Sven Eckelmann

 - improve broadcast queueing, by Linus Lüssing (2 patches)

 - add support for routable IPv4 multicast with bridged setups,
   by Linus Lüssing

 - remove repeated declarations, by Shaokun Zhang

 - fix spelling mistakes, by Zheng Yongjun

 - clean up hard interface handling after dropping sysfs support,
   by Sven Eckelmann (4 patches)
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 76241154 020577f8
......@@ -1849,6 +1849,8 @@ batadv_iv_ogm_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
orig_node->orig) ||
nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
neigh_node->addr) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
neigh_node->if_incoming->net_dev->name) ||
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
neigh_node->if_incoming->net_dev->ifindex) ||
nla_put_u8(msg, BATADV_ATTR_TQ, tq_avg) ||
......@@ -2078,6 +2080,8 @@ batadv_iv_ogm_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
hardif_neigh->addr) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
hardif_neigh->if_incoming->net_dev->name) ||
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
hardif_neigh->if_incoming->net_dev->ifindex) ||
nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
......@@ -2459,6 +2463,8 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid,
router->addr) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
router->if_incoming->net_dev->name) ||
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
router->if_incoming->net_dev->ifindex) ||
nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN,
gw_node->bandwidth_down) ||
nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_UP,
......
......@@ -146,6 +146,8 @@ batadv_v_neigh_dump_neigh(struct sk_buff *msg, u32 portid, u32 seq,
if (nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
hardif_neigh->addr) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
hardif_neigh->if_incoming->net_dev->name) ||
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
hardif_neigh->if_incoming->net_dev->ifindex) ||
nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS,
......@@ -298,6 +300,8 @@ batadv_v_orig_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, orig_node->orig) ||
nla_put(msg, BATADV_ATTR_NEIGH_ADDRESS, ETH_ALEN,
neigh_node->addr) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
neigh_node->if_incoming->net_dev->name) ||
nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
neigh_node->if_incoming->net_dev->ifindex) ||
nla_put_u32(msg, BATADV_ATTR_THROUGHPUT, throughput) ||
......@@ -739,6 +743,12 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid,
goto out;
}
if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
router->if_incoming->net_dev->ifindex)) {
genlmsg_cancel(msg, hdr);
goto out;
}
if (nla_put_u32(msg, BATADV_ATTR_BANDWIDTH_DOWN,
gw_node->bandwidth_down)) {
genlmsg_cancel(msg, hdr);
......
......@@ -395,7 +395,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac,
break;
case BATADV_CLAIM_TYPE_ANNOUNCE:
/* announcement frame
* set HW SRC to the special mac containg the crc
* set HW SRC to the special mac containing the crc
*/
ether_addr_copy(hw_src, mac);
batadv_dbg(BATADV_DBG_BLA, bat_priv,
......@@ -1040,7 +1040,7 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv,
/* lets see if this originator is in our mesh */
orig_node = batadv_orig_hash_find(bat_priv, backbone_addr);
/* dont accept claims from gateways which are not in
/* don't accept claims from gateways which are not in
* the same mesh or group.
*/
if (!orig_node)
......
......@@ -52,7 +52,6 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
void batadv_bla_status_update(struct net_device *net_dev);
int batadv_bla_init(struct batadv_priv *bat_priv);
void batadv_bla_free(struct batadv_priv *bat_priv);
int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb);
#ifdef CONFIG_BATMAN_ADV_DAT
bool batadv_bla_check_claim(struct batadv_priv *bat_priv, u8 *addr,
unsigned short vid);
......
......@@ -9,7 +9,6 @@
#include <linux/atomic.h>
#include <linux/byteorder/generic.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/if.h>
#include <linux/if_arp.h>
......@@ -403,7 +402,7 @@ int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
goto out;
}
/* >1 neighbors -> (re)brodcast */
/* >1 neighbors -> (re)broadcast */
if (rcu_dereference(hlist_next_rcu(first)))
goto out;
......@@ -677,44 +676,17 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
batadv_update_min_mtu(hard_iface->soft_iface);
}
/**
* batadv_master_del_slave() - remove hard_iface from the current master iface
* @slave: the interface enslaved in another master
* @master: the master from which slave has to be removed
*
* Invoke ndo_del_slave on master passing slave as argument. In this way the
* slave is free'd and the master can correctly change its internal state.
*
* Return: 0 on success, a negative value representing the error otherwise
*/
static int batadv_master_del_slave(struct batadv_hard_iface *slave,
struct net_device *master)
{
int ret;
if (!master)
return 0;
ret = -EBUSY;
if (master->netdev_ops->ndo_del_slave)
ret = master->netdev_ops->ndo_del_slave(master, slave->net_dev);
return ret;
}
/**
* batadv_hardif_enable_interface() - Enslave hard interface to soft interface
* @hard_iface: hard interface to add to soft interface
* @net: the applicable net namespace
* @iface_name: name of the soft interface
* @soft_iface: netdev struct of the mesh interface
*
* Return: 0 on success or negative error number in case of failure
*/
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
struct net *net, const char *iface_name)
struct net_device *soft_iface)
{
struct batadv_priv *bat_priv;
struct net_device *soft_iface, *master;
__be16 ethertype = htons(ETH_P_BATMAN);
int max_header_len = batadv_max_header_len();
int ret;
......@@ -724,35 +696,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
kref_get(&hard_iface->refcount);
soft_iface = dev_get_by_name(net, iface_name);
if (!soft_iface) {
soft_iface = batadv_softif_create(net, iface_name);
if (!soft_iface) {
ret = -ENOMEM;
goto err;
}
/* dev_get_by_name() increases the reference counter for us */
dev_hold(soft_iface);
}
if (!batadv_softif_is_valid(soft_iface)) {
pr_err("Can't create batman mesh interface %s: already exists as regular interface\n",
soft_iface->name);
ret = -EINVAL;
goto err_dev;
}
/* check if the interface is enslaved in another virtual one and
* in that case unlink it first
*/
master = netdev_master_upper_dev_get(hard_iface->net_dev);
ret = batadv_master_del_slave(hard_iface, master);
if (ret)
goto err_dev;
dev_hold(soft_iface);
hard_iface->soft_iface = soft_iface;
bat_priv = netdev_priv(hard_iface->soft_iface);
......@@ -810,7 +754,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
err_dev:
hard_iface->soft_iface = NULL;
dev_put(soft_iface);
err:
batadv_hardif_put(hard_iface);
return ret;
}
......
......@@ -16,7 +16,6 @@
#include <linux/rcupdate.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <net/net_namespace.h>
/**
* enum batadv_hard_if_state - State of a hard interface
......@@ -75,7 +74,7 @@ bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
struct batadv_hard_iface*
batadv_hardif_get_by_netdev(const struct net_device *net_dev);
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
struct net *net, const char *iface_name);
struct net_device *soft_iface);
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface);
int batadv_hardif_min_mtu(struct net_device *soft_iface);
void batadv_update_min_mtu(struct net_device *soft_iface);
......
......@@ -18,7 +18,7 @@
#include <linux/stddef.h>
#include <linux/types.h>
/* callback to a compare function. should compare 2 element datas for their
/* callback to a compare function. should compare 2 element data for their
* keys
*
* Return: true if same and false if not same
......
......@@ -13,7 +13,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2021.1"
#define BATADV_SOURCE_VERSION "2021.2"
#endif
/* B.A.T.M.A.N. parameters */
......@@ -88,7 +88,6 @@
/* number of packets to send for broadcasts on different interface types */
#define BATADV_NUM_BCASTS_DEFAULT 1
#define BATADV_NUM_BCASTS_WIRELESS 3
#define BATADV_NUM_BCASTS_MAX 3
/* length of the single packet used by the TP meter */
#define BATADV_TP_PACKET_LEN ETH_DATA_LEN
......
......@@ -193,53 +193,22 @@ static u8 batadv_mcast_mla_rtr_flags_softif_get(struct batadv_priv *bat_priv,
* BATADV_MCAST_WANT_NO_RTR6: No IPv6 multicast router is present
* The former two OR'd: no multicast router is present
*/
#if IS_ENABLED(CONFIG_IPV6)
static u8 batadv_mcast_mla_rtr_flags_bridge_get(struct batadv_priv *bat_priv,
struct net_device *bridge)
{
struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list);
struct net_device *dev = bat_priv->soft_iface;
struct br_ip_list *br_ip_entry, *tmp;
u8 flags = BATADV_MCAST_WANT_NO_RTR6;
int ret;
u8 flags = BATADV_NO_FLAGS;
if (!bridge)
return BATADV_MCAST_WANT_NO_RTR4 | BATADV_MCAST_WANT_NO_RTR6;
/* TODO: ask the bridge if a multicast router is present (the bridge
* is capable of performing proper RFC4286 multicast router
* discovery) instead of searching for a ff02::2 listener here
*/
ret = br_multicast_list_adjacent(dev, &bridge_mcast_list);
if (ret < 0)
return BATADV_NO_FLAGS;
list_for_each_entry_safe(br_ip_entry, tmp, &bridge_mcast_list, list) {
/* the bridge snooping does not maintain IPv4 link-local
* addresses - therefore we won't find any IPv4 multicast router
* address here, only IPv6 ones
*/
if (br_ip_entry->addr.proto == htons(ETH_P_IPV6) &&
ipv6_addr_is_ll_all_routers(&br_ip_entry->addr.dst.ip6))
flags &= ~BATADV_MCAST_WANT_NO_RTR6;
list_del(&br_ip_entry->list);
kfree(br_ip_entry);
}
if (!br_multicast_has_router_adjacent(dev, ETH_P_IP))
flags |= BATADV_MCAST_WANT_NO_RTR4;
if (!br_multicast_has_router_adjacent(dev, ETH_P_IPV6))
flags |= BATADV_MCAST_WANT_NO_RTR6;
return flags;
}
#else
static inline u8
batadv_mcast_mla_rtr_flags_bridge_get(struct batadv_priv *bat_priv,
struct net_device *bridge)
{
if (bridge)
return BATADV_NO_FLAGS;
else
return BATADV_MCAST_WANT_NO_RTR4 | BATADV_MCAST_WANT_NO_RTR6;
}
#endif
/**
* batadv_mcast_mla_rtr_flags_get() - get multicast router flags
......
......@@ -814,6 +814,10 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg,
bat_priv->soft_iface->ifindex))
goto nla_put_failure;
if (nla_put_string(msg, BATADV_ATTR_MESH_IFNAME,
bat_priv->soft_iface->name))
goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
net_dev->ifindex) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
......@@ -1045,6 +1049,10 @@ static int batadv_netlink_vlan_fill(struct sk_buff *msg,
bat_priv->soft_iface->ifindex))
goto nla_put_failure;
if (nla_put_string(msg, BATADV_ATTR_MESH_IFNAME,
bat_priv->soft_iface->name))
goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK))
goto nla_put_failure;
......
......@@ -1182,9 +1182,9 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_bcast_packet *bcast_packet;
struct ethhdr *ethhdr;
int hdr_size = sizeof(*bcast_packet);
int ret = NET_RX_DROP;
s32 seq_diff;
u32 seqno;
int ret;
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
......@@ -1210,7 +1210,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
goto free_skb;
if (bcast_packet->ttl < 2)
if (bcast_packet->ttl-- < 2)
goto free_skb;
orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig);
......@@ -1249,7 +1249,9 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
batadv_skb_set_priority(skb, sizeof(struct batadv_bcast_packet));
/* rebroadcast packet */
batadv_add_bcast_packet_to_list(bat_priv, skb, 1, false);
ret = batadv_forw_bcast_packet(bat_priv, skb, 0, false);
if (ret == NETDEV_TX_BUSY)
goto free_skb;
/* don't hand the broadcast up if it is from an originator
* from the same backbone.
......@@ -1275,6 +1277,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
spin_unlock_bh(&orig_node->bcast_seqno_lock);
free_skb:
kfree_skb(skb);
ret = NET_RX_DROP;
out:
if (orig_node)
batadv_orig_node_put(orig_node);
......
......@@ -737,57 +737,48 @@ void batadv_forw_packet_ogmv1_queue(struct batadv_priv *bat_priv,
}
/**
* batadv_add_bcast_packet_to_list() - queue broadcast packet for multiple sends
* batadv_forw_bcast_packet_to_list() - queue broadcast packet for transmissions
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to add
* @delay: number of jiffies to wait before sending
* @own_packet: true if it is a self-generated broadcast packet
* @if_in: the interface where the packet was received on
* @if_out: the outgoing interface to queue on
*
* add a broadcast packet to the queue and setup timers. broadcast packets
* Adds a broadcast packet to the queue and sets up timers. Broadcast packets
* are sent multiple times to increase probability for being received.
*
* The skb is not consumed, so the caller should make sure that the
* skb is freed.
*
* Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
*/
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb,
unsigned long delay,
bool own_packet)
static int batadv_forw_bcast_packet_to_list(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet,
struct batadv_hard_iface *if_in,
struct batadv_hard_iface *if_out)
{
struct batadv_hard_iface *primary_if;
struct batadv_forw_packet *forw_packet;
struct batadv_bcast_packet *bcast_packet;
unsigned long send_time = jiffies;
struct sk_buff *newskb;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
goto err;
newskb = skb_copy(skb, GFP_ATOMIC);
if (!newskb) {
batadv_hardif_put(primary_if);
if (!newskb)
goto err;
}
forw_packet = batadv_forw_packet_alloc(primary_if, NULL,
forw_packet = batadv_forw_packet_alloc(if_in, if_out,
&bat_priv->bcast_queue_left,
bat_priv, newskb);
batadv_hardif_put(primary_if);
if (!forw_packet)
goto err_packet_free;
/* as we have a copy now, it is safe to decrease the TTL */
bcast_packet = (struct batadv_bcast_packet *)newskb->data;
bcast_packet->ttl--;
forw_packet->own = own_packet;
INIT_DELAYED_WORK(&forw_packet->delayed_work,
batadv_send_outstanding_bcast_packet);
batadv_forw_packet_bcast_queue(bat_priv, forw_packet, jiffies + delay);
send_time += delay ? delay : msecs_to_jiffies(5);
batadv_forw_packet_bcast_queue(bat_priv, forw_packet, send_time);
return NETDEV_TX_OK;
err_packet_free:
......@@ -796,10 +787,220 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
return NETDEV_TX_BUSY;
}
/**
* batadv_forw_bcast_packet_if() - forward and queue a broadcast packet
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to add
* @delay: number of jiffies to wait before sending
* @own_packet: true if it is a self-generated broadcast packet
* @if_in: the interface where the packet was received on
* @if_out: the outgoing interface to forward to
*
* Transmits a broadcast packet on the specified interface either immediately
* or if a delay is given after that. Furthermore, queues additional
* retransmissions if this interface is a wireless one.
*
* Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
*/
static int batadv_forw_bcast_packet_if(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet,
struct batadv_hard_iface *if_in,
struct batadv_hard_iface *if_out)
{
unsigned int num_bcasts = if_out->num_bcasts;
struct sk_buff *newskb;
int ret = NETDEV_TX_OK;
if (!delay) {
newskb = skb_copy(skb, GFP_ATOMIC);
if (!newskb)
return NETDEV_TX_BUSY;
batadv_send_broadcast_skb(newskb, if_out);
num_bcasts--;
}
/* delayed broadcast or rebroadcasts? */
if (num_bcasts >= 1) {
BATADV_SKB_CB(skb)->num_bcasts = num_bcasts;
ret = batadv_forw_bcast_packet_to_list(bat_priv, skb, delay,
own_packet, if_in,
if_out);
}
return ret;
}
/**
* batadv_send_no_broadcast() - check whether (re)broadcast is necessary
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to check
* @own_packet: true if it is a self-generated broadcast packet
* @if_out: the outgoing interface checked and considered for (re)broadcast
*
* Return: False if a packet needs to be (re)broadcasted on the given interface,
* true otherwise.
*/
static bool batadv_send_no_broadcast(struct batadv_priv *bat_priv,
struct sk_buff *skb, bool own_packet,
struct batadv_hard_iface *if_out)
{
struct batadv_hardif_neigh_node *neigh_node = NULL;
struct batadv_bcast_packet *bcast_packet;
u8 *orig_neigh;
u8 *neigh_addr;
char *type;
int ret;
if (!own_packet) {
neigh_addr = eth_hdr(skb)->h_source;
neigh_node = batadv_hardif_neigh_get(if_out,
neigh_addr);
}
bcast_packet = (struct batadv_bcast_packet *)skb->data;
orig_neigh = neigh_node ? neigh_node->orig : NULL;
ret = batadv_hardif_no_broadcast(if_out, bcast_packet->orig,
orig_neigh);
if (neigh_node)
batadv_hardif_neigh_put(neigh_node);
/* ok, may broadcast */
if (!ret)
return false;
/* no broadcast */
switch (ret) {
case BATADV_HARDIF_BCAST_NORECIPIENT:
type = "no neighbor";
break;
case BATADV_HARDIF_BCAST_DUPFWD:
type = "single neighbor is source";
break;
case BATADV_HARDIF_BCAST_DUPORIG:
type = "single neighbor is originator";
break;
default:
type = "unknown";
}
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"BCAST packet from orig %pM on %s suppressed: %s\n",
bcast_packet->orig,
if_out->net_dev->name, type);
return true;
}
/**
* __batadv_forw_bcast_packet() - forward and queue a broadcast packet
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to add
* @delay: number of jiffies to wait before sending
* @own_packet: true if it is a self-generated broadcast packet
*
* Transmits a broadcast packet either immediately or if a delay is given
* after that. Furthermore, queues additional retransmissions on wireless
* interfaces.
*
* This call clones the given skb, hence the caller needs to take into
* account that the data segment of the given skb might not be
* modifiable anymore.
*
* Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
*/
static int __batadv_forw_bcast_packet(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet)
{
struct batadv_hard_iface *hard_iface;
struct batadv_hard_iface *primary_if;
int ret = NETDEV_TX_OK;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
return NETDEV_TX_BUSY;
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
if (hard_iface->soft_iface != bat_priv->soft_iface)
continue;
if (!kref_get_unless_zero(&hard_iface->refcount))
continue;
if (batadv_send_no_broadcast(bat_priv, skb, own_packet,
hard_iface)) {
batadv_hardif_put(hard_iface);
continue;
}
ret = batadv_forw_bcast_packet_if(bat_priv, skb, delay,
own_packet, primary_if,
hard_iface);
batadv_hardif_put(hard_iface);
if (ret == NETDEV_TX_BUSY)
break;
}
rcu_read_unlock();
batadv_hardif_put(primary_if);
return ret;
}
/**
* batadv_forw_bcast_packet() - forward and queue a broadcast packet
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to add
* @delay: number of jiffies to wait before sending
* @own_packet: true if it is a self-generated broadcast packet
*
* Transmits a broadcast packet either immediately or if a delay is given
* after that. Furthermore, queues additional retransmissions on wireless
* interfaces.
*
* Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors.
*/
int batadv_forw_bcast_packet(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet)
{
return __batadv_forw_bcast_packet(bat_priv, skb, delay, own_packet);
}
/**
* batadv_send_bcast_packet() - send and queue a broadcast packet
* @bat_priv: the bat priv with all the soft interface information
* @skb: broadcast packet to add
* @delay: number of jiffies to wait before sending
* @own_packet: true if it is a self-generated broadcast packet
*
* Transmits a broadcast packet either immediately or if a delay is given
* after that. Furthermore, queues additional retransmissions on wireless
* interfaces.
*
* Consumes the provided skb.
*/
void batadv_send_bcast_packet(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet)
{
__batadv_forw_bcast_packet(bat_priv, skb, delay, own_packet);
consume_skb(skb);
}
/**
* batadv_forw_packet_bcasts_left() - check if a retransmission is necessary
* @forw_packet: the forwarding packet to check
* @hard_iface: the interface to check on
*
* Checks whether a given packet has any (re)transmissions left on the provided
* interface.
......@@ -811,28 +1012,20 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
* Return: True if (re)transmissions are left, false otherwise.
*/
static bool
batadv_forw_packet_bcasts_left(struct batadv_forw_packet *forw_packet,
struct batadv_hard_iface *hard_iface)
batadv_forw_packet_bcasts_left(struct batadv_forw_packet *forw_packet)
{
unsigned int max;
if (hard_iface)
max = hard_iface->num_bcasts;
else
max = BATADV_NUM_BCASTS_MAX;
return BATADV_SKB_CB(forw_packet->skb)->num_bcasts < max;
return BATADV_SKB_CB(forw_packet->skb)->num_bcasts;
}
/**
* batadv_forw_packet_bcasts_inc() - increment retransmission counter of a
* batadv_forw_packet_bcasts_dec() - decrement retransmission counter of a
* packet
* @forw_packet: the packet to increase the counter for
* @forw_packet: the packet to decrease the counter for
*/
static void
batadv_forw_packet_bcasts_inc(struct batadv_forw_packet *forw_packet)
batadv_forw_packet_bcasts_dec(struct batadv_forw_packet *forw_packet)
{
BATADV_SKB_CB(forw_packet->skb)->num_bcasts++;
BATADV_SKB_CB(forw_packet->skb)->num_bcasts--;
}
/**
......@@ -843,30 +1036,30 @@ batadv_forw_packet_bcasts_inc(struct batadv_forw_packet *forw_packet)
*/
bool batadv_forw_packet_is_rebroadcast(struct batadv_forw_packet *forw_packet)
{
return BATADV_SKB_CB(forw_packet->skb)->num_bcasts > 0;
unsigned char num_bcasts = BATADV_SKB_CB(forw_packet->skb)->num_bcasts;
return num_bcasts != forw_packet->if_outgoing->num_bcasts;
}
/**
* batadv_send_outstanding_bcast_packet() - transmit a queued broadcast packet
* @work: work queue item
*
* Transmits a queued broadcast packet and if necessary reschedules it.
*/
static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
{
struct batadv_hard_iface *hard_iface;
struct batadv_hardif_neigh_node *neigh_node;
struct delayed_work *delayed_work;
unsigned long send_time = jiffies + msecs_to_jiffies(5);
struct batadv_forw_packet *forw_packet;
struct batadv_bcast_packet *bcast_packet;
struct sk_buff *skb1;
struct net_device *soft_iface;
struct delayed_work *delayed_work;
struct batadv_priv *bat_priv;
unsigned long send_time = jiffies + msecs_to_jiffies(5);
struct sk_buff *skb1;
bool dropped = false;
u8 *neigh_addr;
u8 *orig_neigh;
int ret = 0;
delayed_work = to_delayed_work(work);
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
delayed_work);
soft_iface = forw_packet->if_incoming->soft_iface;
bat_priv = netdev_priv(soft_iface);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
dropped = true;
......@@ -878,76 +1071,15 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
goto out;
}
bcast_packet = (struct batadv_bcast_packet *)forw_packet->skb->data;
/* rebroadcast packet */
rcu_read_lock();
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
if (hard_iface->soft_iface != soft_iface)
continue;
if (!batadv_forw_packet_bcasts_left(forw_packet, hard_iface))
continue;
if (forw_packet->own) {
neigh_node = NULL;
} else {
neigh_addr = eth_hdr(forw_packet->skb)->h_source;
neigh_node = batadv_hardif_neigh_get(hard_iface,
neigh_addr);
}
orig_neigh = neigh_node ? neigh_node->orig : NULL;
ret = batadv_hardif_no_broadcast(hard_iface, bcast_packet->orig,
orig_neigh);
if (ret) {
char *type;
switch (ret) {
case BATADV_HARDIF_BCAST_NORECIPIENT:
type = "no neighbor";
break;
case BATADV_HARDIF_BCAST_DUPFWD:
type = "single neighbor is source";
break;
case BATADV_HARDIF_BCAST_DUPORIG:
type = "single neighbor is originator";
break;
default:
type = "unknown";
}
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "BCAST packet from orig %pM on %s suppressed: %s\n",
bcast_packet->orig,
hard_iface->net_dev->name, type);
if (neigh_node)
batadv_hardif_neigh_put(neigh_node);
continue;
}
if (neigh_node)
batadv_hardif_neigh_put(neigh_node);
if (!kref_get_unless_zero(&hard_iface->refcount))
continue;
/* send a copy of the saved skb */
skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
if (skb1)
batadv_send_broadcast_skb(skb1, hard_iface);
batadv_hardif_put(hard_iface);
}
rcu_read_unlock();
/* send a copy of the saved skb */
skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
if (!skb1)
goto out;
batadv_forw_packet_bcasts_inc(forw_packet);
batadv_send_broadcast_skb(skb1, forw_packet->if_outgoing);
batadv_forw_packet_bcasts_dec(forw_packet);
/* if we still have some more bcasts to send */
if (batadv_forw_packet_bcasts_left(forw_packet, NULL)) {
if (batadv_forw_packet_bcasts_left(forw_packet)) {
batadv_forw_packet_bcast_queue(bat_priv, forw_packet,
send_time);
return;
......
......@@ -39,10 +39,14 @@ int batadv_send_broadcast_skb(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface);
int batadv_send_unicast_skb(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node);
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
const struct sk_buff *skb,
unsigned long delay,
bool own_packet);
int batadv_forw_bcast_packet(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet);
void batadv_send_bcast_packet(struct batadv_priv *bat_priv,
struct sk_buff *skb,
unsigned long delay,
bool own_packet);
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface);
......
......@@ -26,7 +26,6 @@
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/percpu.h>
#include <linux/printk.h>
#include <linux/random.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
......@@ -37,6 +36,7 @@
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <net/net_namespace.h>
#include <net/netlink.h>
#include <uapi/linux/batadv_packet.h>
#include <uapi/linux/batman_adv.h>
......@@ -191,7 +191,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
struct vlan_ethhdr *vhdr;
unsigned int header_len = 0;
int data_len = skb->len, ret;
unsigned long brd_delay = 1;
unsigned long brd_delay = 0;
bool do_bcast = false, client_added;
unsigned short vid;
u32 seqno;
......@@ -330,7 +330,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
bcast_packet = (struct batadv_bcast_packet *)skb->data;
bcast_packet->version = BATADV_COMPAT_VERSION;
bcast_packet->ttl = BATADV_TTL;
bcast_packet->ttl = BATADV_TTL - 1;
/* batman packet type: broadcast */
bcast_packet->packet_type = BATADV_BCAST;
......@@ -346,13 +346,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
seqno = atomic_inc_return(&bat_priv->bcast_seqno);
bcast_packet->seqno = htonl(seqno);
batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay, true);
/* a copy is stored in the bcast list, therefore removing
* the original skb.
*/
consume_skb(skb);
batadv_send_bcast_packet(bat_priv, skb, brd_delay, true);
/* unicast packet */
} else {
/* DHCP packets going to a server will use the GW feature */
......@@ -848,14 +842,13 @@ static int batadv_softif_slave_add(struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct batadv_hard_iface *hard_iface;
struct net *net = dev_net(dev);
int ret = -EINVAL;
hard_iface = batadv_hardif_get_by_netdev(slave_dev);
if (!hard_iface || hard_iface->soft_iface)
goto out;
ret = batadv_hardif_enable_interface(hard_iface, net, dev->name);
ret = batadv_hardif_enable_interface(hard_iface, dev);
out:
if (hard_iface)
......@@ -1092,38 +1085,6 @@ static int batadv_softif_newlink(struct net *src_net, struct net_device *dev,
return register_netdevice(dev);
}
/**
* batadv_softif_create() - Create and register soft interface
* @net: the applicable net namespace
* @name: name of the new soft interface
*
* Return: newly allocated soft_interface, NULL on errors
*/
struct net_device *batadv_softif_create(struct net *net, const char *name)
{
struct net_device *soft_iface;
int ret;
soft_iface = alloc_netdev(sizeof(struct batadv_priv), name,
NET_NAME_UNKNOWN, batadv_softif_init_early);
if (!soft_iface)
return NULL;
dev_net_set(soft_iface, net);
soft_iface->rtnl_link_ops = &batadv_link_ops;
ret = register_netdevice(soft_iface);
if (ret < 0) {
pr_err("Unable to register the batman interface '%s': %i\n",
name, ret);
free_netdev(soft_iface);
return NULL;
}
return soft_iface;
}
/**
* batadv_softif_destroy_netlink() - deletion of batadv_soft_interface via
* netlink
......
......@@ -12,14 +12,12 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <net/net_namespace.h>
#include <net/rtnetlink.h>
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len);
void batadv_interface_rx(struct net_device *soft_iface,
struct sk_buff *skb, int hdr_size,
struct batadv_orig_node *orig_node);
struct net_device *batadv_softif_create(struct net *net, const char *name);
bool batadv_softif_is_valid(const struct net_device *net_dev);
extern struct rtnl_link_ops batadv_link_ops;
int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid);
......
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