WCG内核修改
1. 下载源代码包
从 http://vault.centos.org 下载内核源代码RPM包
2. 安装源代码包
[root@wcg-9-73 df]# rpm -ivh kernel-3.10.0-1062.el7.src.rpm
执行命令后会生成/root/rpmbuild路径,包含SPECS和SOURCES
3. 修改源码
[root@wcg-9-73 df]# cd /root/rpmbuild/SOURCES
[root@wcg-9-73 SOURCES]# xz -d linux-3.10.0-1062.el7.tar.xz
[root@wcg-9-73 SOURCES]# tar -xvf linux-3.10.0-1062.el7.tar
#将修改后的代码替换
[root@wcg-9-73 SOURCES]# cd linux-3.10.0-1062.el7/
[root@wcg-9-73 linux-3.10.0-1062.el]# cd net/ipv4/
[root@wcg-9-73 ipv4]# rm -rf udp.c && cp -rf /root/df/udp.c .
[root@wcg-9-73 ipv4]# cd ../../include/uapi/linux/
[root@wcg-9-73 linux]# rm -rf udp.h && cp -rf /root/df/udp.h .
[root@wcg-9-73 linux]# cd ../../../
[root@wcg-9-73 SOURCES]# tar -cvf linux-3.10.0-1062.el7.tar linux-3.10.0-1062.el7
[root@wcg-9-73 SOURCES]# xz -zv linux-3.10.0-1062.el7.tar
4. 编译打包
[root@wcg-9-73 SOURCES]# cd ..
[root@wcg-9-73 rpmbuild]# nohup rpmbuild -bb SPECS/kernel.spec &
#只编译kernel rpm
[root@wcg-9-73 rpmbuild]# rpmbuild -bb --without debug --without debuginfo --without tools --without perf --without doc SPECS/kernel.spec
kernel-devel和kernel-headers用来开发ko模块,要用到Module.symvers
5. 单独编译kernel
# cd /root/rpmbuild/BUILD/kernel-3.10.0-327.36.3.el7/linux-3.10.0-327.36.3.el7.x86_64
# make -j20 bzImage
6. 替换kernel进行测试
# cp arch/x86/boot/bzImage /boot
# cd /boot
# mv bzImage vmlinuz-3.10.0-327.36.3.el7.x86_64
# reboot
7. 修改的源码
udp.h
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the UDP protocol.
*
* Version: @(#)udp.h 1.0.2 04/28/93
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _UAPI_LINUX_UDP_H
#define _UAPI_LINUX_UDP_H
#include <linux/types.h>
struct udphdr {
__be16 source;
__be16 dest;
__be16 len;
__sum16 check;
};
/* UDP socket options */
#define UDP_CORK 1 /* Never send partially complete segments */
#define UDP_ENCAP 100 /* Set the socket to accept encapsulated packets */
#define UDP_NO_CHECK6_TX 101 /* Disable sending checksum for UDP6X */
#define UDP_NO_CHECK6_RX 102 /* Disable accpeting checksum for UDP6 */
/* UDP encapsulation types */
#define UDP_ENCAP_ESPINUDP_NON_IKE 1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
#define UDP_ENCAP_ESPINUDP 2 /* draft-ietf-ipsec-udp-encaps-06 */
#define UDP_ENCAP_L2TPINUDP 3 /* rfc2661 */
// add by dongfeng 2020-04-13
#define UDP_ENCAP_GTP_DOWN 7
#define UDP_ENCAP_GTP_UP 8
// end add
#endif /* _UAPI_LINUX_UDP_H */
udp.c
...
int sysctl_udp_wmem_min __read_mostly;
EXPORT_SYMBOL(sysctl_udp_wmem_min);
atomic_long_t udp_memory_allocated;
EXPORT_SYMBOL(udp_memory_allocated);
// add by dongfeng 2020-04-13
int (*gtprelay_ko_up_rx_hook)(struct sk_buff *, int ) = NULL;
EXPORT_SYMBOL(gtprelay_ko_up_rx_hook);
int (*gtprelay_ko_down_rx_hook)(struct sk_buff *,int ) = NULL;
EXPORT_SYMBOL(gtprelay_ko_down_rx_hook);
// end add
#define MAX_UDP_PORTS 65536
#define PORTS_PER_CHAIN (MAX_UDP_PORTS / UDP_HTABLE_SIZE_MIN)
...
...
int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct udp_sock *up = udp_sk(sk);
int is_udplite = IS_UDPLITE(sk);
/*
* Charge it to the socket, dropping if the queue is full.
*/
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
goto drop;
nf_reset(skb);
if (static_key_false(&udp_encap_needed) && up->encap_type) {
int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
/*
* This is an encapsulation socket so pass the skb to
* the socket's udp_encap_rcv() hook. Otherwise, just
* fall through and pass this up the UDP socket.
* up->encap_rcv() returns the following value:
* =0 if skb was successfully passed to the encap
* handler or was discarded by it.
* >0 if skb should be passed on to UDP.
* <0 if skb should be resubmitted as proto -N
*/
/* if we're overly short, let UDP handle it */
encap_rcv = ACCESS_ONCE(up->encap_rcv);
if (encap_rcv) {
int ret;
/* Verify checksum before giving to encap */
if (udp_lib_checksum_complete(skb))
goto csum_error;
ret = encap_rcv(sk, skb);
if (ret <= 0) {
UDP_INC_STATS_BH(sock_net(sk),
UDP_MIB_INDATAGRAMS,
is_udplite);
return -ret;
}
}
// add by dongfeng 2020-04-13
switch(up->encap_type) {
case UDP_ENCAP_GTP_DOWN:
// printk("UDP_ENCAP_GTP_DOWN \n");
if(gtprelay_ko_down_rx_hook) {
int ret1 = 0;
ret1 = gtprelay_ko_down_rx_hook(skb,1);
if(ret1 == 1) {
break;
} else if(ret1 == 2) {
kfree_skb(skb);
return 0;
} else {
return 0;
}
}
break;
case UDP_ENCAP_GTP_UP:
//printk("UDP_ENCAP_GTP_UP \n");
if(gtprelay_ko_up_rx_hook) {
int ret1 = 0;
ret1 = gtprelay_ko_up_rx_hook(skb,1);
if(ret1 == 1) {
break;
} else if(ret1 == 2) {
kfree_skb(skb);
return 0;
} else {
return 0;
}
}
break;
default:
break;
}
// end add
/* FALLTHROUGH -- it's a UDP Packet */
}
...
...
/*
* Socket option code for UDP
*/
int udp_lib_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen,
int (*push_pending_frames)(struct sock *))
{
struct udp_sock *up = udp_sk(sk);
int val, valbool;
int err = 0;
int is_udplite = IS_UDPLITE(sk);
if (optlen < sizeof(int))
return -EINVAL;
if (get_user(val, (int __user *)optval))
return -EFAULT;
valbool = val ? 1 : 0;
switch (optname) {
case UDP_CORK:
if (val != 0) {
up->corkflag = 1;
} else {
up->corkflag = 0;
lock_sock(sk);
push_pending_frames(sk);
release_sock(sk);
}
break;
case UDP_ENCAP:
switch (val) {
case 0:
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
up->encap_rcv = xfrm4_udp_encap_rcv;
/* FALLTHROUGH */
case UDP_ENCAP_L2TPINUDP:
up->encap_type = val;
udp_encap_enable();
break;
// add by dongfeng 2020-04-13
case UDP_ENCAP_GTP_DOWN:
case UDP_ENCAP_GTP_UP:
up->encap_type = val;
udp_encap_enable();
//printk("udp_setsockopt %d\n",up->encap_type);
break;
// end add
default:
err = -ENOPROTOOPT;
break;
}
break;
case UDP_NO_CHECK6_TX:
up->no_check6_tx = valbool;
break;
case UDP_NO_CHECK6_RX:
up->no_check6_rx = valbool;
break;
/*
* UDP-Lite's partial checksum coverage (RFC 3828).
*/
/* The sender sets actual checksum coverage length via this option.
* The case coverage > packet length is handled by send module. */
case UDPLITE_SEND_CSCOV:
if (!is_udplite) /* Disable the option on UDP sockets */
return -ENOPROTOOPT;
if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
val = 8;
else if (val > USHRT_MAX)
val = USHRT_MAX;
up->pcslen = val;
up->pcflag |= UDPLITE_SEND_CC;
break;
...