sách gpt4 ăn đã đi

c - 了解 netfilter hook 中的自旋锁

In lại 作者:太空狗 更新时间:2023-10-29 15:38:29 27 4
mua khóa gpt4 giày nike

我正在编写一个小内核模块,用于测量网络数据包退出节点所需的时间。这个模块是 netfilter 库中的一个钩子(Hook)。

对于它接收到的每个数据包,它都会计算一个哈希值,从 skbuff 获取 tstamp 和实际时间戳,并将所有这些数据保存在一个链表中。为了将此数据传递给用户空间,我创建了一个 proc 设备,当用户从该设备读取时,我发送链表的一个条目。

要更改列表(读和写),我有一个自旋锁。问题是有时当我在处理数据包时从 proc 设备读取时系统崩溃。

我认为问题出在函数“dump_data_to_proc”中,更具体地说是在尝试获取自旋锁时。我做了一些测试,它只在 tplink 路由器中运行时崩溃(软锁定)。当我在“普通”PC(单核)上运行该模块时,它不会崩溃,

#include  /* Needed by all modules */ 
#include /* Needed for KERN_INFO */
#include /* Needed for the macros */
#include
#include
#include
#include
#include

#include

#include /* Necessary because of proc fs */
#include /* for copy_from_user */

#include "kmodule_measure_process_time.h"
#include "hash.c"

//DEBUG >=5 is very slow in the tplink
#define DEBUG 2
#define PROCFS_MAX_SIZE 64
#define PROCFS_NAME "measures"
#define MAXIMUM_SAMPLES 10000


static struct nf_hook_ops nfho;
unsigned int total_packets_processed= 0;
unsigned int total_packets_discarded=0;
int temp_counter=0;

struct values_list *HEAD;

spinlock_t list_lock ;


static int hello_proc(struct seq_file *m, void *v) {
seq_printf(m, " stats Mod initialized.\n");
trả về 0;
}

static int proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc, NULL);
}



ssize_t dump_data_to_proc(struct file *filp, char *buffer, size_t length, loff_t *offset){

int bytesRead = 0;
struct values_list *temp=NULL;
int bytesError=0;
char buff[PROCFS_MAX_SIZE];

spin_lock(&list_lock);
temp=HEAD;
if(temp!=NULL){
HEAD = temp->next;
}
spin_unlock(&list_lock);


if(temp!=NULL){
bytesRead = snprintf(buff, PROCFS_MAX_SIZE ,"%u|%llu|%llu\n", temp->hash,temp->arrival_timestap, temp->exit_timestap);
length = length - bytesRead+1;
kfree(temp);
temp_counter--;
}

bytesError= copy_to_user(buffer, buff, bytesRead);

if(bytesError!=0){
#if DEBUG >0
printk(KERN_INFO "Error: failed to copy to user");
#kết thúc nếu
}
return bytesRead;
}


static const struct file_operations proc_fops = {
.owner = THIS_MODULE,
.open = proc_open,
.read = dump_data_to_proc,
.llseek = seq_lseek,
.release = single_release,
};


static unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{

uint32_t hash=0;
ktime_t now_timeval;
struct timespec now;
u64 timestamp_arrival_time=0;
u64 timestamp_now=0;
struct ipv6hdr * ipheader;
struct values_list *node;
int number_of_samples=0;

spin_lock(&list_lock);
number_of_samples=temp_counter;
spin_unlock(&list_lock);

if(number_of_samples > MAXIMUM_SAMPLES){
#if DEBUG > 5
printk(KERN_INFO "Discarded one sample because the list is full.\n");
#kết thúc nếu
total_packets_discarded++; // probably this should be inside a spinlock
return NF_ACCEPT;
}

//calculate arrival time and actual time in ns
timestamp_arrival_time = ktime_to_ns(skb->tstamp);
getnstimeofday(&now);
now_timeval = timespec_to_ktime(now);
timestamp_now = ktime_to_ns(now_timeval);

//get Ipv6 addresses
ipheader = (struct ipv6hdr *)skb_network_header(skb);

hash=simple_hash((char *)&ipheader->saddr,sizeof(struct in6_addr)*2,hash);
total_packets_processed++;


node = (struct values_list *) kmalloc(sizeof(struct values_list),GFP_ATOMIC);
if(!node){
#if DEBUG >0
printk(KERN_INFO "Error cannot malloc\n");
#kết thúc nếu
return NF_ACCEPT;
}

node->hash=hash;
node->arrival_timestap=timestamp_arrival_time;
node->exit_timestap=timestamp_now;

spin_lock(&list_lock);
node->next=HEAD;
HEAD=node;
temp_counter++;
spin_unlock(&list_lock);

return NF_ACCEPT;

}

static int __init init_main(void)
{
nfho.hook = hook_func;
nfho.hooknum = NF_INET_POST_ROUTING;
nfho.pf = PF_INET6;
nfho.priority = NF_IP_PRI_FIRST;
nf_register_hook(&nfho);
#if DEBUG >0
printk(KERN_INFO " kernel module: Successfully inserted protocol module into kernel.\n");
#kết thúc nếu

proc_create(PROCFS_NAME, 0, NULL, &proc_fops);

spin_lock_init(&list_lock);

//Some distros/devices disable timestamping of packets
net_enable_timestamp();

trả về 0;

}


static void __exit cleanup_main(void)
{

struct values_list *temp;

nf_unregister_hook(&nfho);
#if DEBUG >0
printk(KERN_INFO " kernel module: Successfully unloaded protocol module.\n");
printk(KERN_INFO "Number of packets processed:%d\n",total_packets_processed);
printk(KERN_INFO "Number of packets discarded:%d\n",total_packets_discarded);
#kết thúc nếu

remove_proc_entry(PROCFS_NAME, NULL);

while(HEAD!=NULL){
temp=HEAD;
HEAD= HEAD->next;
kfree(temp);
}


}


module_init(init_main);
module_exit(cleanup_main);
/* * Declaring code as GPL. */
MODULE_LICENSE("GPLv3");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);

câu trả lời hay nhất

您的代码有两个问题:

  1. 为您的代码使用 Linux 内核宏。 http://makelinux.com/ldd3/chp-11-sect-5 .只需将 struct list_head 作为元素添加到您的 struct values_list 并使用 list_entrylist_add 和其他

  2. Netfilter hools 在软中断上下文中运行,因此您phảisử dụngspin_lock_irqsavespin_unlock_irqrestore。这很可能是您的系统因软锁定而崩溃的原因。仔细阅读http://makelinux.com/ldd3/chp-5-sect-5

关于c - 了解 netfilter hook 中的自旋锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24814311/

27 4 0
Đề xuất bài viết: c - 两个进程之间的命名共享内存
Đề xuất bài viết: 安卓新文件(路径)
Đề xuất bài viết: android - 可选回调
Đề xuất bài viết: c - 为平均值排序浮点值
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress