root/trunk/batman-adv-kernelland/soft-interface.c @ 1527

Revision 1527, 8.8 kB (checked in by simon, 8 months ago)

batman-adv: Fix regressions found by Coccinelle

Some regressions which were found in the Coccinelle run by Julia Lawall
are fixed in this patch. This includes:

  • fix: use ETH_ALEN for mac address size in initialization
  • use kzalloc() instead of kmalloc() + memset()
  • remove unneccesary returns
  • return NETDEV_TX_OK in interface_tx()

Thanks to Andrew Lunn for informing us about that.

Signed-off-by: Simon Wunderlich <siwu@…>

Line 
1/*
2 * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
3 *
4 * Marek Lindner, Simon Wunderlich
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA
19 *
20 */
21
22#include "main.h"
23#include "soft-interface.h"
24#include "hard-interface.h"
25#include "send.h"
26#include "translation-table.h"
27#include "types.h"
28#include "hash.h"
29#include <linux/ethtool.h>
30#include <linux/etherdevice.h>
31#include "compat.h"
32
33static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
34                                  * broadcast storms */
35static int32_t skb_packets;
36static int32_t skb_bad_packets;
37
38unsigned char mainIfAddr[ETH_ALEN];
39static unsigned char mainIfAddr_default[ETH_ALEN];
40static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
41static void bat_get_drvinfo(struct net_device *dev,
42                            struct ethtool_drvinfo *info);
43static u32 bat_get_msglevel(struct net_device *dev);
44static void bat_set_msglevel(struct net_device *dev, u32 value);
45static u32 bat_get_link(struct net_device *dev);
46static u32 bat_get_rx_csum(struct net_device *dev);
47static int bat_set_rx_csum(struct net_device *dev, u32 data);
48
49static const struct ethtool_ops bat_ethtool_ops = {
50        .get_settings = bat_get_settings,
51        .get_drvinfo = bat_get_drvinfo,
52        .get_msglevel = bat_get_msglevel,
53        .set_msglevel = bat_set_msglevel,
54        .get_link = bat_get_link,
55        .get_rx_csum = bat_get_rx_csum,
56        .set_rx_csum = bat_set_rx_csum
57};
58
59void set_main_if_addr(uint8_t *addr)
60{
61        memcpy(mainIfAddr, addr, ETH_ALEN);
62}
63
64int main_if_was_up(void)
65{
66        return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
67}
68
69int my_skb_push(struct sk_buff *skb, unsigned int len)
70{
71        int result = 0;
72
73        skb_packets++;
74        if (skb_headroom(skb) < len) {
75                skb_bad_packets++;
76                result = pskb_expand_head(skb, len, 0, GFP_ATOMIC);
77
78                if (result < 0)
79                        return result;
80        }
81
82        skb_push(skb, len);
83        return 0;
84}
85
86#ifdef HAVE_NET_DEVICE_OPS
87static const struct net_device_ops bat_netdev_ops = {
88        .ndo_open = interface_open,
89        .ndo_stop = interface_release,
90        .ndo_get_stats = interface_stats,
91        .ndo_set_mac_address = interface_set_mac_addr,
92        .ndo_change_mtu = interface_change_mtu,
93        .ndo_start_xmit = interface_tx,
94        .ndo_validate_addr = eth_validate_addr
95};
96#endif
97
98void interface_setup(struct net_device *dev)
99{
100        struct bat_priv *priv = netdev_priv(dev);
101        char dev_addr[ETH_ALEN];
102
103        ether_setup(dev);
104
105#ifdef HAVE_NET_DEVICE_OPS
106        dev->netdev_ops = &bat_netdev_ops;
107#else
108        dev->open = interface_open;
109        dev->stop = interface_release;
110        dev->get_stats = interface_stats;
111        dev->set_mac_address = interface_set_mac_addr;
112        dev->change_mtu = interface_change_mtu;
113        dev->hard_start_xmit = interface_tx;
114#endif
115        dev->destructor = free_netdev;
116
117        dev->mtu = hardif_min_mtu();
118        dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
119                                                * skbuff for our header */
120
121        /* generate random address */
122        random_ether_addr(dev_addr);
123        memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
124
125        SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
126
127        memset(priv, 0, sizeof(struct bat_priv));
128}
129
130int interface_open(struct net_device *dev)
131{
132        netif_start_queue(dev);
133        return 0;
134}
135
136int interface_release(struct net_device *dev)
137{
138        netif_stop_queue(dev);
139        return 0;
140}
141
142struct net_device_stats *interface_stats(struct net_device *dev)
143{
144        struct bat_priv *priv = netdev_priv(dev);
145        return &priv->stats;
146}
147
148int interface_set_mac_addr(struct net_device *dev, void *p)
149{
150        struct sockaddr *addr = p;
151
152        if (!is_valid_ether_addr(addr->sa_data))
153                return -EADDRNOTAVAIL;
154
155        hna_local_remove(dev->dev_addr, "mac address changed");
156        memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
157        hna_local_add(dev->dev_addr);
158
159        return 0;
160}
161
162int interface_change_mtu(struct net_device *dev, int new_mtu)
163{
164        /* check ranges */
165        if ((new_mtu < 68) || (new_mtu > hardif_min_mtu()))
166                return -EINVAL;
167
168        dev->mtu = new_mtu;
169
170        return 0;
171}
172
173int interface_tx(struct sk_buff *skb, struct net_device *dev)
174{
175        struct unicast_packet *unicast_packet;
176        struct bcast_packet *bcast_packet;
177        struct orig_node *orig_node;
178        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
179        struct bat_priv *priv = netdev_priv(dev);
180        struct batman_if *batman_if;
181        uint8_t dstaddr[6];
182        int data_len = skb->len;
183        unsigned long flags;
184
185        if (atomic_read(&module_state) != MODULE_ACTIVE)
186                goto dropped;
187
188        dev->trans_start = jiffies;
189        /* TODO: check this for locks */
190        hna_local_add(ethhdr->h_source);
191
192        /* ethernet packet should be broadcasted */
193        if (is_bcast(ethhdr->h_dest) || is_mcast(ethhdr->h_dest)) {
194
195                if (my_skb_push(skb, sizeof(struct bcast_packet)) < 0)
196                        goto dropped;
197
198                bcast_packet = (struct bcast_packet *)skb->data;
199                bcast_packet->version = COMPAT_VERSION;
200
201                /* batman packet type: broadcast */
202                bcast_packet->packet_type = BAT_BCAST;
203
204                /* hw address of first interface is the orig mac because only
205                 * this mac is known throughout the mesh */
206                memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN);
207
208                /* set broadcast sequence number */
209                bcast_packet->seqno = htons(bcast_seqno);
210
211                bcast_seqno++;
212
213                /* broadcast packet */
214                add_bcast_packet_to_list(skb);
215                /* a copy is stored in the bcast list, therefore removing
216                 * the original skb. */
217                kfree_skb(skb);
218
219        /* unicast packet */
220        } else {
221                spin_lock_irqsave(&orig_hash_lock, flags);
222                /* get routing information */
223                orig_node = ((struct orig_node *)hash_find(orig_hash,
224                                                           ethhdr->h_dest));
225
226                /* check for hna host */
227                if (!orig_node)
228                        orig_node = transtable_search(ethhdr->h_dest);
229
230                if ((orig_node) &&
231                    (orig_node->batman_if) &&
232                    (orig_node->router)) {
233                        if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
234                                goto unlock;
235
236                        unicast_packet = (struct unicast_packet *)skb->data;
237
238                        unicast_packet->version = COMPAT_VERSION;
239                        /* batman packet type: unicast */
240                        unicast_packet->packet_type = BAT_UNICAST;
241                        /* set unicast ttl */
242                        unicast_packet->ttl = TTL;
243                        /* copy the destination for faster routing */
244                        memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
245
246                        /* net_dev won't be available when not active */
247                        if (orig_node->batman_if->if_active != IF_ACTIVE)
248                                goto unlock;
249
250                        /* don't lock while sending the packets ... we therefore
251                         * copy the required data before sending */
252
253                        batman_if = orig_node->batman_if;
254                        memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
255                        spin_unlock_irqrestore(&orig_hash_lock, flags);
256
257                        send_skb_packet(skb, batman_if, dstaddr);
258                } else {
259                        goto unlock;
260                }
261        }
262
263        priv->stats.tx_packets++;
264        priv->stats.tx_bytes += data_len;
265        goto end;
266
267unlock:
268        spin_unlock_irqrestore(&orig_hash_lock, flags);
269dropped:
270        priv->stats.tx_dropped++;
271end:
272        return NETDEV_TX_OK;
273}
274
275void interface_rx(struct sk_buff *skb, int hdr_size)
276{
277        struct net_device *dev = soft_device;
278        struct bat_priv *priv = netdev_priv(dev);
279
280        /* check if enough space is available for pulling, and pull */
281        if (!pskb_may_pull(skb, hdr_size)) {
282                kfree_skb(skb);
283                return;
284        }
285        skb_pull_rcsum(skb, hdr_size);
286/*      skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
287
288        skb->dev = dev;
289        skb->protocol = eth_type_trans(skb, dev);
290
291        /* should not be neccesary anymore as we use skb_pull_rcsum()
292         * TODO: please verify this and remove this TODO
293         * -- Dec 21st 2009, Simon Wunderlich */
294
295/*      skb->ip_summed = CHECKSUM_UNNECESSARY;*/
296
297        /* TODO: set skb->pkt_type to PACKET_BROADCAST, PACKET_MULTICAST,
298         * PACKET_OTHERHOST or PACKET_HOST */
299
300        priv->stats.rx_packets++;
301        priv->stats.rx_bytes += skb->len;
302
303        dev->last_rx = jiffies;
304
305        netif_rx(skb);
306}
307
308/* ethtool */
309static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
310{
311        cmd->supported = 0;
312        cmd->advertising = 0;
313        cmd->speed = SPEED_10;
314        cmd->duplex = DUPLEX_FULL;
315        cmd->port = PORT_TP;
316        cmd->phy_address = 0;
317        cmd->transceiver = XCVR_INTERNAL;
318        cmd->autoneg = AUTONEG_DISABLE;
319        cmd->maxtxpkt = 0;
320        cmd->maxrxpkt = 0;
321
322        return 0;
323}
324
325static void bat_get_drvinfo(struct net_device *dev,
326                            struct ethtool_drvinfo *info)
327{
328        strcpy(info->driver, "B.A.T.M.A.N. advanced");
329        strcpy(info->version, SOURCE_VERSION);
330        strcpy(info->fw_version, "N/A");
331        strcpy(info->bus_info, "batman");
332}
333
334static u32 bat_get_msglevel(struct net_device *dev)
335{
336        return -EOPNOTSUPP;
337}
338
339static void bat_set_msglevel(struct net_device *dev, u32 value)
340{
341}
342
343static u32 bat_get_link(struct net_device *dev)
344{
345        return 1;
346}
347
348static u32 bat_get_rx_csum(struct net_device *dev)
349{
350        return 0;
351}
352
353static int bat_set_rx_csum(struct net_device *dev, u32 data)
354{
355        return -EOPNOTSUPP;
356}
Note: See TracBrowser for help on using the browser.