6lowpan: remove skb_deliver from IPHC
authorMartin Townsend <mtownsend1973@gmail.com>
Thu, 23 Oct 2014 14:40:53 +0000 (15:40 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 27 Oct 2014 14:51:15 +0000 (15:51 +0100)
Separating skb delivery from decompression ensures that we can support further
decompression schemes and removes the mixed return value of error codes with
NET_RX_FOO.

Signed-off-by: Martin Townsend <mtownsend1973@gmail.com>
Acked-by: Alexander Aring <alex.aring@gmail.com>
Acked-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/6lowpan.h
net/6lowpan/iphc.c
net/bluetooth/6lowpan.c
net/ieee802154/6lowpan_rtnl.c

index d184df1d0d412360a6de44024b9559afc9d13a07..abfa3593e911399b3e983e1ae2f06545baa7aa92 100644 (file)
@@ -372,12 +372,10 @@ lowpan_uncompress_size(const struct sk_buff *skb, u16 *dgram_offset)
        return skb->len + uncomp_header - ret;
 }
 
-typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
-
 int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
                const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
                const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-               u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
+               u8 iphc0, u8 iphc1);
 int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
                        unsigned short type, const void *_daddr,
                        const void *_saddr, unsigned int len);
index 747b3ccfc4f811424f65855950e8fec09c5b565b..45714fe885f0c9bab75493961ddbec4c1e6abd09 100644 (file)
@@ -171,29 +171,6 @@ static int uncompress_context_based_src_addr(struct sk_buff *skb,
        return 0;
 }
 
-static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr,
-                      struct net_device *dev, skb_delivery_cb deliver_skb)
-{
-       int stat;
-
-       skb_push(skb, sizeof(struct ipv6hdr));
-       skb_reset_network_header(skb);
-       skb_copy_to_linear_data(skb, hdr, sizeof(struct ipv6hdr));
-
-       skb->protocol = htons(ETH_P_IPV6);
-       skb->pkt_type = PACKET_HOST;
-       skb->dev = dev;
-
-       raw_dump_table(__func__, "raw skb data dump before receiving",
-                      skb->data, skb->len);
-
-       stat = deliver_skb(skb, dev);
-
-       consume_skb(skb);
-
-       return stat;
-}
-
 /* Uncompress function for multicast destination address,
  * when M bit is set.
  */
@@ -327,7 +304,7 @@ static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
 int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
                        const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
                        const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
-                       u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb)
+                       u8 iphc0, u8 iphc1)
 {
        struct ipv6hdr hdr = {};
        u8 tmp, num_context = 0;
@@ -492,10 +469,13 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
                hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
                hdr.hop_limit, &hdr.daddr);
 
-       raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
+       skb_push(skb, sizeof(hdr));
+       skb_reset_network_header(skb);
+       skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
 
-       return skb_deliver(skb, &hdr, dev, deliver_skb);
+       raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
 
+       return 0;
 drop:
        kfree_skb(skb);
        return -EINVAL;
index 6c5c2eff45bd88e782a8b33fa44c7fe35e21349f..45d9a9fef634aebfdad12d7b3779e1c02051833d 100644 (file)
@@ -252,7 +252,7 @@ static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
 
        skb_cp = skb_copy(skb, GFP_ATOMIC);
        if (!skb_cp)
-               return -ENOMEM;
+               return NET_RX_DROP;
 
        return netif_rx(skb_cp);
 }
@@ -290,7 +290,7 @@ static int process_data(struct sk_buff *skb, struct net_device *netdev,
        return lowpan_process_data(skb, netdev,
                                   saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
                                   daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
-                                  iphc0, iphc1, give_skb_to_upper);
+                                  iphc0, iphc1);
 
 drop:
        kfree_skb(skb);
@@ -350,6 +350,16 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
                        if (ret != NET_RX_SUCCESS)
                                goto drop;
 
+                       local_skb->protocol = htons(ETH_P_IPV6);
+                       local_skb->pkt_type = PACKET_HOST;
+                       local_skb->dev = dev;
+
+                       if (give_skb_to_upper(local_skb, dev)
+                                       != NET_RX_SUCCESS) {
+                               kfree_skb(local_skb);
+                               goto drop;
+                       }
+
                        dev->stats.rx_bytes += skb->len;
                        dev->stats.rx_packets++;
 
index 1779a08d110a5b9be37c396d031a8e976ff35949..15c7717c5e069eec4537b9e5b3712a27d26addd8 100644 (file)
@@ -141,20 +141,28 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb,
        struct sk_buff *skb_cp;
        int stat = NET_RX_SUCCESS;
 
+       skb->protocol = htons(ETH_P_IPV6);
+       skb->pkt_type = PACKET_HOST;
+
        rcu_read_lock();
        list_for_each_entry_rcu(entry, &lowpan_devices, list)
                if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
                        skb_cp = skb_copy(skb, GFP_ATOMIC);
                        if (!skb_cp) {
-                               stat = -ENOMEM;
-                               break;
+                               kfree_skb(skb);
+                               rcu_read_unlock();
+                               return NET_RX_DROP;
                        }
 
                        skb_cp->dev = entry->ldev;
                        stat = netif_rx(skb_cp);
+                       if (stat == NET_RX_DROP)
+                               break;
                }
        rcu_read_unlock();
 
+       consume_skb(skb);
+
        return stat;
 }
 
@@ -190,8 +198,7 @@ static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 
        return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
                                   IEEE802154_ADDR_LEN, dap, da.addr_type,
-                                  IEEE802154_ADDR_LEN, iphc0, iphc1,
-                                  lowpan_give_skb_to_devices);
+                                  IEEE802154_ADDR_LEN, iphc0, iphc1);
 
 drop:
        kfree_skb(skb);
@@ -528,44 +535,48 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
 
        /* check that it's our buffer */
        if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
-               skb->protocol = htons(ETH_P_IPV6);
-               skb->pkt_type = PACKET_HOST;
-
                /* Pull off the 1-byte of 6lowpan header. */
                skb_pull(skb, 1);
-
-               ret = lowpan_give_skb_to_devices(skb, NULL);
-               if (ret == NET_RX_DROP)
-                       goto drop;
+               return lowpan_give_skb_to_devices(skb, NULL);
        } else {
                switch (skb->data[0] & 0xe0) {
                case LOWPAN_DISPATCH_IPHC:      /* ipv6 datagram */
                        ret = process_data(skb, &hdr);
                        if (ret == NET_RX_DROP)
                                goto drop;
-                       break;
+
+                       return lowpan_give_skb_to_devices(skb, NULL);
                case LOWPAN_DISPATCH_FRAG1:     /* first fragment header */
                        ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
                        if (ret == 1) {
                                ret = process_data(skb, &hdr);
                                if (ret == NET_RX_DROP)
                                        goto drop;
+
+                               return lowpan_give_skb_to_devices(skb, NULL);
+                       } else if (ret == -1) {
+                               return NET_RX_DROP;
+                       } else {
+                               return NET_RX_SUCCESS;
                        }
-                       break;
                case LOWPAN_DISPATCH_FRAGN:     /* next fragments headers */
                        ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
                        if (ret == 1) {
                                ret = process_data(skb, &hdr);
                                if (ret == NET_RX_DROP)
                                        goto drop;
+
+                               return lowpan_give_skb_to_devices(skb, NULL);
+                       } else if (ret == -1) {
+                               return NET_RX_DROP;
+                       } else {
+                               return NET_RX_SUCCESS;
                        }
-                       break;
                default:
                        break;
                }
        }
 
-       return NET_RX_SUCCESS;
 drop_skb:
        kfree_skb(skb);
 drop: