genode/repos/dde_linux/src/lib/lxip/driver.c
Christian Helmuth d5518aa938 lib/vfs/lxip: support configuration of MTU
The MTU can be set via the "mtu" attribute like follows.

  <vfs> <lxip mtu="1200" dhcp="yes"/> </vfs>
2017-11-30 11:23:18 +01:00

141 lines
2.6 KiB
C

/*
* \brief Back-end driver for IP stack
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2013-09-04
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Linux includes */
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
/* local includes */
#include <lx_emul.h>
#include <nic.h>
static struct net_device *_dev;
static int driver_net_open(struct net_device *dev)
{
_dev = dev;
return 0;
}
static int driver_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *stats = (struct net_device_stats*) netdev_priv(dev);
int len = skb->len;
void* addr = skb->data;
/* transmit to nic-session */
if (net_tx(addr, len)) {
/* tx queue is full, could not enqueue packet */
pr_debug("TX packet dropped\n");
return NETDEV_TX_BUSY;
}
dev_kfree_skb(skb);
/* save timestamp */
dev->trans_start = jiffies;
stats->tx_packets++;
stats->tx_bytes += len;
return NETDEV_TX_OK;
}
static int driver_change_mtu(struct net_device *dev, int new_mtu)
{
/* possible point to reflect successful MTU setting */
return eth_change_mtu(dev, new_mtu);
}
static const struct net_device_ops driver_net_ops =
{
.ndo_open = driver_net_open,
.ndo_start_xmit = driver_net_xmit,
.ndo_change_mtu = driver_change_mtu,
};
static int driver_init(void)
{
struct net_device *dev;
int err = -ENODEV;
dev = alloc_etherdev(0);
if (!(dev = alloc_etherdev(0)))
goto out;
dev->netdev_ops = &driver_net_ops;
/* set MAC */
net_mac(dev->dev_addr, ETH_ALEN);
if ((err = register_netdev(dev))) {
panic("driver: Could not register back-end %d\n", err);
goto out_free;
}
return 0;
out_free:
free_netdev(dev);
out:
return err;
}
module_init(driver_init);
/**
* Called by Nic_client when a packet was received
*/
void net_driver_rx(void *addr, unsigned long size)
{
struct net_device_stats *stats;
if (!_dev)
return;
stats = (struct net_device_stats*) netdev_priv(_dev);
/* allocate skb */
enum {
ADDITIONAL_HEADROOM = 4, /* smallest value found by trial & error */
};
struct sk_buff *skb = dev_alloc_skb(size + ADDITIONAL_HEADROOM);
if (!skb) {
printk(KERN_NOTICE "genode_net_rx: low on mem - packet dropped!\n");
stats->rx_dropped++;
return;
}
/* copy packet */
memcpy(skb_put(skb, size), addr, size);
skb->dev = _dev;
skb->protocol = eth_type_trans(skb, _dev);
skb->ip_summed = CHECKSUM_NONE;
netif_receive_skb(skb);
stats->rx_packets++;
stats->rx_bytes += size;
}