ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with broadcast indication but unicast recipient */
- if (!is_broadcast_ether_addr(ethhdr->h_dest))
+ if (!is_bcast(ethhdr->h_dest))
return NET_RX_DROP;
/* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ if (is_bcast(ethhdr->h_source))
return NET_RX_DROP;
/* create a copy of the skb, if needed, to modify it. */
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */
- if (is_broadcast_ether_addr(ethhdr->h_dest))
+ if (is_bcast(ethhdr->h_dest))
return NET_RX_DROP;
/* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ if (is_bcast(ethhdr->h_source))
return NET_RX_DROP;
/* not for me */
/* find a suitable router for this originator, and use
* bonding if possible. */
-struct neigh_node *find_router(struct orig_node *orig_node,
+struct neigh_node *find_router(struct bat_priv *bat_priv,
+ struct orig_node *orig_node,
struct batman_if *recv_if)
{
- struct bat_priv *bat_priv;
struct orig_node *primary_orig_node;
struct orig_node *router_orig;
struct neigh_node *router, *first_candidate, *best_router;
/* without bonding, the first node should
* always choose the default router. */
- if (!recv_if)
- return orig_node->router;
-
- bat_priv = netdev_priv(recv_if->soft_iface);
- bonding_enabled = atomic_read(&bat_priv->bonding_enabled);
+ bonding_enabled = atomic_read(&bat_priv->bonding);
- if (!bonding_enabled)
+ if ((!recv_if) && (!bonding_enabled))
return orig_node->router;
router_orig = orig_node->router->orig_node;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with unicast indication but broadcast recipient */
- if (is_broadcast_ether_addr(ethhdr->h_dest))
+ if (is_bcast(ethhdr->h_dest))
return -1;
/* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ if (is_bcast(ethhdr->h_source))
return -1;
/* not for me */
return 0;
}
-static int route_unicast_packet(struct sk_buff *skb,
- struct batman_if *recv_if, int hdr_size)
+int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
+ int hdr_size)
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct orig_node *orig_node;
unsigned long flags;
struct unicast_packet *unicast_packet;
struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
+ int ret;
+ struct sk_buff *new_skb;
unicast_packet = (struct unicast_packet *)skb->data;
- /* packet for me */
- if (is_my_mac(unicast_packet->dest)) {
- interface_rx(recv_if->soft_iface, skb, hdr_size);
- return NET_RX_SUCCESS;
- }
-
/* TTL exceeded */
if (unicast_packet->ttl < 2) {
pr_debug("Warning - can't forward unicast packet from %pM to "
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, unicast_packet->dest));
- router = find_router(orig_node, recv_if);
+ router = find_router(bat_priv, orig_node, recv_if);
if (!router) {
spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
return NET_RX_DROP;
unicast_packet = (struct unicast_packet *)skb->data;
- ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+ if (unicast_packet->packet_type == BAT_UNICAST &&
+ atomic_read(&bat_priv->fragmentation) &&
+ skb->len > batman_if->net_dev->mtu)
+ return frag_send_skb(skb, bat_priv, batman_if,
+ dstaddr);
+
+ if (unicast_packet->packet_type == BAT_UNICAST_FRAG &&
+ 2 * skb->len - hdr_size <= batman_if->net_dev->mtu) {
+
+ ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
+
+ if (ret == NET_RX_DROP)
+ return NET_RX_DROP;
+
+ /* packet was buffered for late merge */
+ if (!new_skb)
+ return NET_RX_SUCCESS;
+
+ skb = new_skb;
+ unicast_packet = (struct unicast_packet *)skb->data;
+ }
/* decrement ttl */
unicast_packet->ttl--;
/* packet for me */
if (is_my_mac(unicast_packet->dest)) {
- interface_rx(recv_if->soft_iface, skb, hdr_size);
+ interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
return NET_RX_SUCCESS;
}
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct unicast_frag_packet *unicast_packet;
- struct orig_node *orig_node;
- struct frag_packet_list_entry *tmp_frag_entry;
int hdr_size = sizeof(struct unicast_frag_packet);
- unsigned long flags;
+ struct sk_buff *new_skb = NULL;
+ int ret;
if (check_unicast_packet(skb, hdr_size) < 0)
return NET_RX_DROP;
/* packet for me */
if (is_my_mac(unicast_packet->dest)) {
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
- orig_node = ((struct orig_node *)
- hash_find(bat_priv->orig_hash, unicast_packet->orig));
+ ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
- if (!orig_node) {
- pr_debug("couldn't find orig node for fragmentation\n");
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock,
- flags);
+ if (ret == NET_RX_DROP)
return NET_RX_DROP;
- }
- orig_node->last_frag_packet = jiffies;
-
- if (list_empty(&orig_node->frag_list) &&
- create_frag_buffer(&orig_node->frag_list)) {
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock,
- flags);
- return NET_RX_DROP;
- }
-
- tmp_frag_entry =
- search_frag_packet(&orig_node->frag_list,
- unicast_packet);
-
- if (!tmp_frag_entry) {
- create_frag_entry(&orig_node->frag_list, skb);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock,
- flags);
+ /* packet was buffered for late merge */
+ if (!new_skb)
return NET_RX_SUCCESS;
- }
-
- skb = merge_frag_packet(&orig_node->frag_list,
- tmp_frag_entry, skb);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
- if (!skb)
- return NET_RX_DROP;
- interface_rx(recv_if->soft_iface, skb, hdr_size);
+ interface_rx(recv_if->soft_iface, new_skb, recv_if,
+ sizeof(struct unicast_packet));
return NET_RX_SUCCESS;
}
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* packet with broadcast indication but unicast recipient */
- if (!is_broadcast_ether_addr(ethhdr->h_dest))
+ if (!is_bcast(ethhdr->h_dest))
return NET_RX_DROP;
/* packet with broadcast sender address */
- if (is_broadcast_ether_addr(ethhdr->h_source))
+ if (is_bcast(ethhdr->h_source))
return NET_RX_DROP;
/* ignore broadcasts sent by myself */
add_bcast_packet_to_list(bat_priv, skb);
/* broadcast for me */
- interface_rx(recv_if->soft_iface, skb, hdr_size);
+ interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
return NET_RX_SUCCESS;
}