|
@@ -549,6 +549,7 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
|
* @bat_priv: the bat priv with all the soft interface information
|
|
* @bat_priv: the bat priv with all the soft interface information
|
|
* @skb: broadcast packet to add
|
|
* @skb: broadcast packet to add
|
|
* @delay: number of jiffies to wait before sending
|
|
* @delay: number of jiffies to wait before sending
|
|
|
|
+ * @own_packet: true if it is a self-generated broadcast packet
|
|
*
|
|
*
|
|
* add a broadcast packet to the queue and setup timers. broadcast packets
|
|
* add a broadcast packet to the queue and setup timers. broadcast packets
|
|
* are sent multiple times to increase probability for being received.
|
|
* are sent multiple times to increase probability for being received.
|
|
@@ -560,7 +561,8 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
|
*/
|
|
*/
|
|
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
|
int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
|
const struct sk_buff *skb,
|
|
const struct sk_buff *skb,
|
|
- unsigned long delay)
|
|
|
|
|
|
+ unsigned long delay,
|
|
|
|
+ bool own_packet)
|
|
{
|
|
{
|
|
struct batadv_hard_iface *primary_if;
|
|
struct batadv_hard_iface *primary_if;
|
|
struct batadv_forw_packet *forw_packet;
|
|
struct batadv_forw_packet *forw_packet;
|
|
@@ -587,6 +589,7 @@ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
|
|
bcast_packet->ttl--;
|
|
bcast_packet->ttl--;
|
|
|
|
|
|
forw_packet->skb = newskb;
|
|
forw_packet->skb = newskb;
|
|
|
|
+ forw_packet->own = own_packet;
|
|
|
|
|
|
INIT_DELAYED_WORK(&forw_packet->delayed_work,
|
|
INIT_DELAYED_WORK(&forw_packet->delayed_work,
|
|
batadv_send_outstanding_bcast_packet);
|
|
batadv_send_outstanding_bcast_packet);
|
|
@@ -603,11 +606,16 @@ err:
|
|
static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
|
|
static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
|
|
{
|
|
{
|
|
struct batadv_hard_iface *hard_iface;
|
|
struct batadv_hard_iface *hard_iface;
|
|
|
|
+ struct batadv_hardif_neigh_node *neigh_node;
|
|
struct delayed_work *delayed_work;
|
|
struct delayed_work *delayed_work;
|
|
struct batadv_forw_packet *forw_packet;
|
|
struct batadv_forw_packet *forw_packet;
|
|
|
|
+ struct batadv_bcast_packet *bcast_packet;
|
|
struct sk_buff *skb1;
|
|
struct sk_buff *skb1;
|
|
struct net_device *soft_iface;
|
|
struct net_device *soft_iface;
|
|
struct batadv_priv *bat_priv;
|
|
struct batadv_priv *bat_priv;
|
|
|
|
+ u8 *neigh_addr;
|
|
|
|
+ u8 *orig_neigh;
|
|
|
|
+ int ret = 0;
|
|
|
|
|
|
delayed_work = to_delayed_work(work);
|
|
delayed_work = to_delayed_work(work);
|
|
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
|
|
forw_packet = container_of(delayed_work, struct batadv_forw_packet,
|
|
@@ -625,6 +633,8 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
|
|
if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet))
|
|
if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet))
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
|
|
+ bcast_packet = (struct batadv_bcast_packet *)forw_packet->skb->data;
|
|
|
|
+
|
|
/* rebroadcast packet */
|
|
/* rebroadcast packet */
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
|
|
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
|
|
@@ -634,6 +644,49 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
|
|
if (forw_packet->num_packets >= hard_iface->num_bcasts)
|
|
if (forw_packet->num_packets >= hard_iface->num_bcasts)
|
|
continue;
|
|
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 surpressed: %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))
|
|
if (!kref_get_unless_zero(&hard_iface->refcount))
|
|
continue;
|
|
continue;
|
|
|
|
|