linux内核网络模块初探测 (二)

修改了昨天写的模块,更改了网卡类型,更改了网卡mac,最后插入模块后结果如下:

============================

/ #

/ #

/ # insmod test.ko

/ # ifconfig -a

eth0      Link encap:Ethernet  HWaddr 00:E0:4A:BC:15:E7  

         inet addr:192.168.10.20  Bcast:192.168.10.255  Mask:255.255.255.0

         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

         RX packets:1672 errors:0 dropped:0 overruns:0 frame:0

         TX packets:662 errors:0 dropped:0 overruns:0 carrier:0

         collisions:0 txqueuelen:1000

         RX bytes:2208249 (2.1 MiB)  TX bytes:108432 (105.8 KiB)

         Interrupt:108 Base address:0x300


lo        Link encap:Local Loopback  

         inet addr:127.0.0.1  Mask:255.0.0.0

         UP LOOPBACK RUNNING  MTU:16436  Metric:1

         RX packets:0 errors:0 dropped:0 overruns:0 frame:0

         TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

         collisions:0 txqueuelen:0

         RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


sx        Link encap:Ethernet  HWaddr 00:26:7A:01:02:03  

         UP BROADCAST  MTU:1500  Metric:1

         RX packets:0 errors:0 dropped:0 overruns:0 frame:0

         TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

         collisions:0 txqueuelen:0

         RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


/ # lsmod

test 2944 0 - Live 0xbf000000

/ # uname -a

Linux 192.168.10.20 2.6.28.6 #1 Mon Nov 7 17:44:34 CST 2011 armv6l GNU/Linux

/ #

============================


代码如下:

#include <linux/kernel.h>

#include <linux/jiffies.h>

#include <linux/module.h>

#include <linux/interrupt.h>

#include <linux/fs.h>

#include <linux/types.h>

#include <linux/string.h>

#include <linux/socket.h>

#include <linux/errno.h>

#include <linux/fcntl.h>

#include <linux/in.h>

#include <linux/init.h>


#include <asm/system.h>

#include <asm/uaccess.h>

#include <asm/io.h>


#include <linux/inet.h>

#include <linux/netdevice.h>

#include <linux/etherdevice.h>

#include <linux/skbuff.h>

#include <linux/ethtool.h>

#include <net/sock.h>

#include <net/checksum.h>

#include <linux/if_ether.h>/* For the statistics structure. */

#include <linux/if_arp.h>/* For ARPHRD_ETHER */

#include <linux/ip.h>

#include <linux/tcp.h>

#include <linux/percpu.h>

#include <linux/etherdevice.h>

#include <net/net_namespace.h>


struct pcpu_lstats {

unsigned long packets;

unsigned long bytes;

};

extern int register_pernet_device(struct pernet_operations *ops);

// extern const struct header_ops eth_header_ops;


const struct header_ops eth_header_ops ____cacheline_aligned = {

.create= eth_header,

.parse= eth_header_parse,

.rebuild= eth_rebuild_header,

.cache= eth_header_cache,

.cache_update= eth_header_cache_update,

};




/*

* The higher levels take care of making this non-reentrant (it's

* called with bh's disabled).

*/

static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)

{

struct pcpu_lstats *pcpu_lstats, *lb_stats;


skb_orphan(skb);


skb->protocol = eth_type_trans(skb,dev);


dev->last_rx = jiffies;


/* it's OK to use per_cpu_ptr() because BHs are off */

pcpu_lstats = dev->ml_priv;

lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());

lb_stats->bytes += skb->len;

lb_stats->packets++;


netif_rx(skb);


return 0;

}


static struct net_device_stats *get_stats(struct net_device *dev)

{

const struct pcpu_lstats *pcpu_lstats;

struct net_device_stats *stats = &dev->stats;

unsigned long bytes = 0;

unsigned long packets = 0;

int i;


pcpu_lstats = dev->ml_priv;

for_each_possible_cpu(i) {

const struct pcpu_lstats *lb_stats;


lb_stats = per_cpu_ptr(pcpu_lstats, i);

bytes   += lb_stats->bytes;

packets += lb_stats->packets;

}

stats->rx_packets = packets;

stats->tx_packets = packets;

stats->rx_bytes = bytes;

stats->tx_bytes = bytes;

return stats;

}


static u32 always_on(struct net_device *dev)

{

return 1;

}


static const struct ethtool_ops loopback_ethtool_ops = {

.get_link= always_on,

.set_tso= ethtool_op_set_tso,

.get_tx_csum= always_on,

.get_sg= always_on,

.get_rx_csum= always_on,

};


static int loopback_dev_init(struct net_device *dev)

{

struct pcpu_lstats *lstats;


lstats = alloc_percpu(struct pcpu_lstats);

if (!lstats)

return -ENOMEM;


dev->ml_priv = lstats;

return 0;

}


static void loopback_dev_free(struct net_device *dev)

{

struct pcpu_lstats *lstats = dev->ml_priv;


free_percpu(lstats);

free_netdev(dev);

}


/*

* The loopback device is special. There is only one instance

* per network namespace.

*/

static void loopback_setup(struct net_device *dev)

{

dev->get_stats= &get_stats;

dev->mtu= 1500;

dev->hard_start_xmit= loopback_xmit;

dev->hard_header_len= ETH_HLEN;/* 14*/

dev->addr_len= ETH_ALEN;/* 6*/

dev->tx_queue_len= 0;

// dev->type= ARPHRD_LOOPBACK;// 0x0001

dev->type= ARPHRD_ETHER;

// dev->flags= IFF_LOOPBACK;

dev->flags= IFF_UP | IFF_BROADCAST;

// dev->features = NETIF_F_SG | NETIF_F_FRAGLIST

// | NETIF_F_TSO

// | NETIF_F_NO_CSUM

// | NETIF_F_HIGHDMA

// | NETIF_F_LLTX

// | NETIF_F_NETNS_LOCAL;

dev->ethtool_ops= &loopback_ethtool_ops;

dev->header_ops= &eth_header_ops;

dev->init = loopback_dev_init;

dev->destructor = loopback_dev_free;

// strcpy(dev->dev_addr,"000001");

dev->dev_addr[0] = 0x0;

dev->dev_addr[1] = 0x26;

dev->dev_addr[2] = 0x7a;

dev->dev_addr[3] = 0x01;

dev->dev_addr[4] = 0x02;

dev->dev_addr[5] = 0x03;

}


/* Setup and register the loopback device. */

static __net_init int loopback_net_init(struct net *net)

{

struct net_device *dev;

int err;


err = -ENOMEM;

dev = alloc_netdev(0, "sx", loopback_setup);

if (!dev)

goto out;


dev_net_set(dev, net);

err = register_netdev(dev);

if (err)

goto out_free_netdev;


net->loopback_dev = dev;

return 0;



out_free_netdev:

free_netdev(dev);

out:

if (net == &init_net)

panic("loopback: Failed to register netdevice: %d\n", err);

return err;

}


static __net_exit void loopback_net_exit(struct net *net)

{

struct net_device *dev = net->loopback_dev;


unregister_netdev(dev);

}


static struct pernet_operations __net_initdata loopback_net_ops = {

      .init = loopback_net_init,

      .exit = loopback_net_exit,

};


static int __init loopback_init(void)

{

return register_pernet_device(&loopback_net_ops);

}


/* Loopback is special. It should be initialized before any other network

* device and network subsystem.

*/

fs_initcall(loopback_init);

// module_init(loopback_init);

module_exit(loopback_net_exit);

MODULE_LICENSE("GPL");


好的,今天的实验到此为止,明天继续吧

你可能感兴趣的:(linux,模块,内核,网卡注册)