作者squallbbking (阿爽BB)
看板LinuxDev
標題[問題] kernel socket 產生 bug:scheduling while atomic問題
時間Mon Jun 13 16:23:11 2011
不好意思 小弟在Kernel 接收封包得地方(net/ipv4/ip_input.c)中的ip_rcv中
加入發送kernel socket 的函式 sock_sendmsg,目前程式可以順利發送封包至我
設定的目的端,但是我發現kernel中會印出"BUG : scheduling while atomic..."
等等一大串訊息,重點是發送一陣子後我的module就會當掉,小弟覺得是這個BUG所影響
,上網爬了一下文有某些外國網站有提到此問題,不過沒有明確的解決辦法,不知道
有沒有高手大大能替小弟解惑一下,這是滿重要的問題,拜託好心人幫忙一下了><
萬分感謝!!!!
不好意思,補上程式碼,有點長我擷取重點部分,如果還有需要請在跟我說
,真的非常感謝!!
這是kernel中修改的部分,路徑如我上文中
int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
*pt, struct net_device *orig_dev)
{
struct iphdr *iph;
u32 len;
//這裡開始是我增加連結MODULE的地方
int check11;
if(pkt_input)
{
pkt_input(skb);
}
if(multicast)
{
check11 = multicast(skb);
if(check11==1)
{
//printk("now drop\n");
goto drop;
}
}
//以上是我增加的部分,pkt_input回傳 check11為0就送出封包,為1就goto drop
.
.
.
inhdr_error:
IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
drop:
kfree_skb(skb);
out:
return NET_RX_DROP;
接下來是module code
init_module(void)部分先創此socket
//========merge kernel socket========//
socket_sendmeg = kmalloc(sizeof(struct socketpair) , GFP_KERNEL);
memset(socket_sendmeg , 0 , sizeof(struct socketpair));
if((err=sock_create(PF_PACKET , SOCK_PACKET , htons(ETH_P_IP) ,
&socket_sendmeg->sock)))
{
printk("create socket err!\n");
return 0;
}
createsocketmeg(pktinfm);
再來連結地址和類型
void createsocketmeg(struct pktinf *pktinfm)
{
char DEV[]="eth1"; //140.117.157.50
memset(&socket_sendmeg->addr,0,sizeof(struct sockaddr));
strcpy(socket_sendmeg->addr.sa_data , DEV);
socket_sendmeg->addr.sa_family = PF_PACKET;
msgmeg.msg_flags=0;
msgmeg.msg_name=&socket_sendmeg->addr;
msgmeg.msg_namelen=sizeof(struct sockaddr);
msgmeg.msg_control=NULL;
msgmeg.msg_controllen=0;
msgmeg.msg_iovlen=1;
msgmeg.msg_control=NULL;
};
最後要送出封包時,module會呼叫此函式,製作ethernet、IP、TCP的header然後
加入payload送出
void C2_sendto_c1( mm_segment_t oldfs , unsigned char *megbuf , int *mbuf
,int pkt)
{
src_port_csc = 0x5000;
dest_port_csc = pktinfm->IPC1_destport;
ACK_NO_csc = htonl(pktinfm-> C1img_end_ack);
//------------Ether header build---------------//
memset(&Ethmeg , 0 , sizeof(Ethmeg));
Get_Hw_Addr(mac_sadr_csc, mac_sor_csc);
memcpy(Ethmeg.eth.h_source , mac_sadr_csc , ETH_ALEN);
Get_Hw_Addr(mac_dadr_csc , mac_des_csc);
memcpy(Ethmeg.eth.h_dest, mac_dadr_csc , ETH_ALEN);
Ethmeg.eth.h_proto = htons(ETH_P_IP);
memcpy(C1pkt , &Ethmeg.eth , 14);
//------------IP header build---------------//
memset(&Ipmeg , 0 , sizeof(Ipmeg));
set_ip_ihl( &Ipmeg.iph );
set_ip_version( &Ipmeg.iph ,IPVERSION);
set_ip_tos( &Ipmeg.iph ,tos);
tot_len_csc = 0x0028 +mbuf[pkt] ;
set_ip_tot_len( &Ipmeg.iph ,tot_len_csc);
pktinfm->C1img_end_ID = set_ip_id( &Ipmeg.iph ,pktinfm->C1img_end_ID);
set_ip_frag_off( &Ipmeg.iph ,frag_off);
set_ip_ttl( &Ipmeg.iph ,ttl_csc);
set_ip_protocol( &Ipmeg.iph ,IPPROTO_TCP);
set_ip_saddr( &Ipmeg.iph ,source_ip_csc);
set_ip_daddr( &Ipmeg.iph ,dest_ip_csc);
set_ip_check( &Ipmeg.iph);
memcpy( C1pkt+sizeof(Ethmeg) , &Ipmeg.iph , 20);
//------------TCP header build---------------//
memset(&Tcpmeg , 0 , sizeof(Tcpmeg));
set_tcp_source( &Tcpmeg.tcph ,src_port_csc);
set_tcp_dest( &Tcpmeg.tcph ,dest_port_csc);
seq_csc = htonl(pktinfm-> C1img_end_seq) + pktinfm-> C1img_end_len;
set_tcp_seq( &Tcpmeg.tcph ,seq_csc);
pktinfm-> C1img_end_seq = Tcpmeg.tcph.seq;
pktinfm-> C1img_end_len = mbuf[pkt];
set_tcp_ack_seq( &Tcpmeg.tcph ,ACK_NO_csc);
set_tcp_res1( &Tcpmeg.tcph ,res1);
set_tcp_doff( &Tcpmeg.tcph ,doff);
set_tcp_cwr(&Tcpmeg.tcph , cwr);
set_tcp_ece(&Tcpmeg.tcph , ece);
set_tcp_urg(&Tcpmeg.tcph , urg);
set_tcp_ack(&Tcpmeg.tcph , ack);
set_tcp_psh(&Tcpmeg.tcph , psh);
set_tcp_rst(&Tcpmeg.tcph , rst);
set_tcp_syn(&Tcpmeg.tcph , syn);
set_tcp_fin(&Tcpmeg.tcph , fin);
set_tcp_window( &Tcpmeg.tcph , winmeg);
set_tcp_urg_ptr( &Tcpmeg.tcph , Urp);
memcpy(C1pkt+sizeof(Ethmeg)+sizeof(Ipmeg), &Tcpmeg.tcph , 20);
//------------payload build---------------//
memcpy( C1pkt+sizeof(Ethmeg)+sizeof(Ipmeg)+sizeof(Tcpmeg) , megbuf ,
mbuf[pkt]);
set_tcp_check_meg( &Tcpmeg.tcph , &Ipmeg.iph ,
C1pkt+sizeof(Ethmeg)+sizeof(Ipmeg)+sizeof(Tcpmeg));
memcpy(C1pkt+sizeof(Ethmeg)+sizeof(Ipmeg)+16, &Tcpmeg.tcph.check , 2);
//-------end header build----------------//
iovmeg.iov_base= C1pkt;
iovmeg.iov_len = sizeof(C1pkt);
msgmeg.msg_iov = &iovmeg;
oldfs = get_fs();
set_fs(KERNEL_DS);
//這裡送出封包
sock_sendmsg(socket_sendmeg->sock , &msgmeg, sizeof(C1pkt));
//printk("merg for C1C2\n") ;
set_fs(oldfs);
};
大致上是這樣,如有需要提供的請在跟我說,我查到說呼叫sock_sendmsg會產生此BUG
,不好意思文章有點長,但這問題非常重要,拜託了!!!再次萬分感謝
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.117.164.24
→ pico2k:請提供程式碼... 06/13 16:31
※ 編輯: squallbbking 來自: 140.117.164.24 (06/13 17:01)
→ franklin:你可以用schedule_work看看 06/14 10:07