Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a40d9b07 authored by Simon Wunderlich's avatar Simon Wunderlich Committed by Antonio Quartulli
Browse files

batman-adv: fix header alignment by unrolling batadv_header



The size of the batadv_header of 3 is problematic on some architectures
which automatically pad all structures to a 32 bit boundary. To not lose
performance by packing this struct, better embed it into the various
host structures.

Reported-by: default avatarRussell King <linux@arm.linux.org.uk>
Signed-off-by: default avatarSimon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: default avatarMarek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: default avatarAntonio Quartulli <antonio@meshcoding.com>
parent 46b76e0b
Loading
Loading
Loading
Loading
+18 −18
Original line number Original line Diff line number Diff line
@@ -307,9 +307,9 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
	hard_iface->bat_iv.ogm_buff = ogm_buff;
	hard_iface->bat_iv.ogm_buff = ogm_buff;


	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
	batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
	batadv_ogm_packet->packet_type = BATADV_IV_OGM;
	batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
	batadv_ogm_packet->version = BATADV_COMPAT_VERSION;
	batadv_ogm_packet->header.ttl = 2;
	batadv_ogm_packet->ttl = 2;
	batadv_ogm_packet->flags = BATADV_NO_FLAGS;
	batadv_ogm_packet->flags = BATADV_NO_FLAGS;
	batadv_ogm_packet->reserved = 0;
	batadv_ogm_packet->reserved = 0;
	batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
	batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
@@ -346,7 +346,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)


	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
	batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
	batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
	batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
	batadv_ogm_packet->header.ttl = BATADV_TTL;
	batadv_ogm_packet->ttl = BATADV_TTL;
}
}


/* when do we schedule our own ogm to be sent */
/* when do we schedule our own ogm to be sent */
@@ -435,7 +435,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
			   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->ttl,
			   (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
			   (batadv_ogm_packet->flags & BATADV_DIRECTLINK ?
			    "on" : "off"),
			    "on" : "off"),
			   hard_iface->net_dev->name,
			   hard_iface->net_dev->name,
@@ -491,7 +491,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
	/* multihomed peer assumed
	/* multihomed peer assumed
	 * non-primary OGMs are only broadcasted on their interface
	 * non-primary OGMs are only broadcasted on their interface
	 */
	 */
	if ((directlink && (batadv_ogm_packet->header.ttl == 1)) ||
	if ((directlink && (batadv_ogm_packet->ttl == 1)) ||
	    (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
	    (forw_packet->own && (forw_packet->if_incoming != primary_if))) {
		/* FIXME: what about aggregated packets ? */
		/* FIXME: what about aggregated packets ? */
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -499,7 +499,7 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet)
			   (forw_packet->own ? "Sending own" : "Forwarding"),
			   (forw_packet->own ? "Sending own" : "Forwarding"),
			   batadv_ogm_packet->orig,
			   batadv_ogm_packet->orig,
			   ntohl(batadv_ogm_packet->seqno),
			   ntohl(batadv_ogm_packet->seqno),
			   batadv_ogm_packet->header.ttl,
			   batadv_ogm_packet->ttl,
			   forw_packet->if_incoming->net_dev->name,
			   forw_packet->if_incoming->net_dev->name,
			   forw_packet->if_incoming->net_dev->dev_addr);
			   forw_packet->if_incoming->net_dev->dev_addr);


@@ -572,7 +572,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
		 */
		 */
		if ((!directlink) &&
		if ((!directlink) &&
		    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
		    (!(batadv_ogm_packet->flags & BATADV_DIRECTLINK)) &&
		    (batadv_ogm_packet->header.ttl != 1) &&
		    (batadv_ogm_packet->ttl != 1) &&


		    /* own packets originating non-primary
		    /* own packets originating non-primary
		     * interfaces leave only that interface
		     * interfaces leave only that interface
@@ -587,7 +587,7 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,
		 * interface only - we still can aggregate
		 * interface only - we still can aggregate
		 */
		 */
		if ((directlink) &&
		if ((directlink) &&
		    (new_bat_ogm_packet->header.ttl == 1) &&
		    (new_bat_ogm_packet->ttl == 1) &&
		    (forw_packet->if_incoming == if_incoming) &&
		    (forw_packet->if_incoming == if_incoming) &&


		    /* packets from direct neighbors or
		    /* packets from direct neighbors or
@@ -778,7 +778,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
	struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
	uint16_t tvlv_len;
	uint16_t tvlv_len;


	if (batadv_ogm_packet->header.ttl <= 1) {
	if (batadv_ogm_packet->ttl <= 1) {
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv, "ttl exceeded\n");
		return;
		return;
	}
	}
@@ -798,7 +798,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,


	tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);
	tvlv_len = ntohs(batadv_ogm_packet->tvlv_len);


	batadv_ogm_packet->header.ttl--;
	batadv_ogm_packet->ttl--;
	memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
	memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN);


	/* apply hop penalty */
	/* apply hop penalty */
@@ -807,7 +807,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,


	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
	batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
		   "Forwarding packet: tq: %i, ttl: %i\n",
		   "Forwarding packet: tq: %i, ttl: %i\n",
		   batadv_ogm_packet->tq, batadv_ogm_packet->header.ttl);
		   batadv_ogm_packet->tq, batadv_ogm_packet->ttl);


	/* switch of primaries first hop flag when forwarding */
	/* switch of primaries first hop flag when forwarding */
	batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
	batadv_ogm_packet->flags &= ~BATADV_PRIMARIES_FIRST_HOP;
@@ -972,8 +972,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
	spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);
	spin_unlock_bh(&neigh_node->bat_iv.lq_update_lock);


	if (dup_status == BATADV_NO_DUP) {
	if (dup_status == BATADV_NO_DUP) {
		orig_node->last_ttl = batadv_ogm_packet->header.ttl;
		orig_node->last_ttl = batadv_ogm_packet->ttl;
		neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
		neigh_node->last_ttl = batadv_ogm_packet->ttl;
	}
	}


	batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
	batadv_bonding_candidate_add(bat_priv, orig_node, neigh_node);
@@ -1247,7 +1247,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
	 * packet in an aggregation.  Here we expect that the padding
	 * packet in an aggregation.  Here we expect that the padding
	 * is always zero (or not 0x01)
	 * is always zero (or not 0x01)
	 */
	 */
	if (batadv_ogm_packet->header.packet_type != BATADV_IV_OGM)
	if (batadv_ogm_packet->packet_type != BATADV_IV_OGM)
		return;
		return;


	/* could be changed by schedule_own_packet() */
	/* could be changed by schedule_own_packet() */
@@ -1267,8 +1267,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
		   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->tq,
		   ntohl(batadv_ogm_packet->seqno), batadv_ogm_packet->tq,
		   batadv_ogm_packet->header.ttl,
		   batadv_ogm_packet->ttl,
		   batadv_ogm_packet->header.version, has_directlink_flag);
		   batadv_ogm_packet->version, has_directlink_flag);


	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) {
@@ -1433,7 +1433,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
	 * seqno and similar ttl as the non-duplicate
	 * seqno and similar ttl as the non-duplicate
	 */
	 */
	sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
	sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
	similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
	similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->ttl;
	if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
	if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
			    (sameseq && similar_ttl)))
			    (sameseq && similar_ttl)))
		batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
		batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
+3 −3
Original line number Original line Diff line number Diff line
@@ -349,7 +349,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,


	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
	unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;


	switch (unicast_4addr_packet->u.header.packet_type) {
	switch (unicast_4addr_packet->u.packet_type) {
	case BATADV_UNICAST:
	case BATADV_UNICAST:
		batadv_dbg(BATADV_DBG_DAT, bat_priv,
		batadv_dbg(BATADV_DBG_DAT, bat_priv,
			   "* encapsulated within a UNICAST packet\n");
			   "* encapsulated within a UNICAST packet\n");
@@ -374,7 +374,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
			break;
			break;
		default:
		default:
			batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
			batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
				   unicast_4addr_packet->u.header.packet_type);
				   unicast_4addr_packet->u.packet_type);
		}
		}
		break;
		break;
	case BATADV_BCAST:
	case BATADV_BCAST:
@@ -387,7 +387,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
	default:
	default:
		batadv_dbg(BATADV_DBG_DAT, bat_priv,
		batadv_dbg(BATADV_DBG_DAT, bat_priv,
			   "* encapsulated within an unknown packet type (0x%x)\n",
			   "* encapsulated within an unknown packet type (0x%x)\n",
			   unicast_4addr_packet->u.header.packet_type);
			   unicast_4addr_packet->u.packet_type);
	}
	}
}
}


+4 −4
Original line number Original line Diff line number Diff line
@@ -355,7 +355,7 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
		batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
		batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
				   skb->len + ETH_HLEN);
				   skb->len + ETH_HLEN);


		packet->header.ttl--;
		packet->ttl--;
		batadv_send_skb_packet(skb, neigh_node->if_incoming,
		batadv_send_skb_packet(skb, neigh_node->if_incoming,
				       neigh_node->addr);
				       neigh_node->addr);
		ret = true;
		ret = true;
@@ -444,9 +444,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
		goto out_err;
		goto out_err;


	/* Create one header to be copied to all fragments */
	/* Create one header to be copied to all fragments */
	frag_header.header.packet_type = BATADV_UNICAST_FRAG;
	frag_header.packet_type = BATADV_UNICAST_FRAG;
	frag_header.header.version = BATADV_COMPAT_VERSION;
	frag_header.version = BATADV_COMPAT_VERSION;
	frag_header.header.ttl = BATADV_TTL;
	frag_header.ttl = BATADV_TTL;
	frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
	frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
	frag_header.reserved = 0;
	frag_header.reserved = 0;
	frag_header.no = 0;
	frag_header.no = 0;
+3 −3
Original line number Original line Diff line number Diff line
@@ -194,7 +194,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
		goto free_skb;
		goto free_skb;
	}
	}


	if (icmp_header->header.packet_type != BATADV_ICMP) {
	if (icmp_header->packet_type != BATADV_ICMP) {
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
			   "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
			   "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
		len = -EINVAL;
		len = -EINVAL;
@@ -243,9 +243,9 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,


	icmp_header->uid = socket_client->index;
	icmp_header->uid = socket_client->index;


	if (icmp_header->header.version != BATADV_COMPAT_VERSION) {
	if (icmp_header->version != BATADV_COMPAT_VERSION) {
		icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
		icmp_header->msg_type = BATADV_PARAMETER_PROBLEM;
		icmp_header->header.version = BATADV_COMPAT_VERSION;
		icmp_header->version = BATADV_COMPAT_VERSION;
		batadv_socket_add_packet(socket_client, icmp_header,
		batadv_socket_add_packet(socket_client, icmp_header,
					 packet_len);
					 packet_len);
		goto free_skb;
		goto free_skb;
+6 −6
Original line number Original line Diff line number Diff line
@@ -383,17 +383,17 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,


	batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;
	batadv_ogm_packet = (struct batadv_ogm_packet *)skb->data;


	if (batadv_ogm_packet->header.version != BATADV_COMPAT_VERSION) {
	if (batadv_ogm_packet->version != BATADV_COMPAT_VERSION) {
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
		batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
			   "Drop packet: incompatible batman version (%i)\n",
			   "Drop packet: incompatible batman version (%i)\n",
			   batadv_ogm_packet->header.version);
			   batadv_ogm_packet->version);
		goto err_free;
		goto err_free;
	}
	}


	/* all receive handlers return whether they received or reused
	/* all receive handlers return whether they received or reused
	 * the supplied skb. if not, we have to free the skb.
	 * the supplied skb. if not, we have to free the skb.
	 */
	 */
	idx = batadv_ogm_packet->header.packet_type;
	idx = batadv_ogm_packet->packet_type;
	ret = (*batadv_rx_handler[idx])(skb, hard_iface);
	ret = (*batadv_rx_handler[idx])(skb, hard_iface);


	if (ret == NET_RX_DROP)
	if (ret == NET_RX_DROP)
@@ -1119,9 +1119,9 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src,
	skb_reserve(skb, ETH_HLEN);
	skb_reserve(skb, ETH_HLEN);
	tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
	tvlv_buff = skb_put(skb, sizeof(*unicast_tvlv_packet) + tvlv_len);
	unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
	unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)tvlv_buff;
	unicast_tvlv_packet->header.packet_type = BATADV_UNICAST_TVLV;
	unicast_tvlv_packet->packet_type = BATADV_UNICAST_TVLV;
	unicast_tvlv_packet->header.version = BATADV_COMPAT_VERSION;
	unicast_tvlv_packet->version = BATADV_COMPAT_VERSION;
	unicast_tvlv_packet->header.ttl = BATADV_TTL;
	unicast_tvlv_packet->ttl = BATADV_TTL;
	unicast_tvlv_packet->reserved = 0;
	unicast_tvlv_packet->reserved = 0;
	unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
	unicast_tvlv_packet->tvlv_len = htons(tvlv_len);
	unicast_tvlv_packet->align = 0;
	unicast_tvlv_packet->align = 0;
Loading