⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcp.c

📁 DCCP协议在linux下的C编程实现 linux C
💻 C
📖 第 1 页 / 共 5 页
字号:
/* dcp.c - an implemenetation of the DCCP protocol			     *//* ------------------------------------------------------------------------- *//*  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.    This code has been developed by the University of Waikato WAND    research group. For further information please see http://www.wand.net.nz/    This code has been based on the work of other developers:    	Patrick McManus (mcmanus@ducksong.com)	Lulea Univeristy of Technology    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.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     *//* ------------------------------------------------------------------------- */#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/in.h>#include <linux/if_arp.h>#include <linux/init.h>#include <net/checksum.h>#include <net/sock.h>#include <net/ip.h>#include <net/protocol.h>#include <net/inet_common.h>#include <asm/semaphore.h>#include <linux/spinlock.h>#include <linux/timer.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/mm.h>#include <linux/vmalloc.h> //vmalloc ;)/* obviously, for kmalloc */ /* for struct file_operations, register_chrdev() */ #include <linux/fs.h>/* this header files wraps some common module-space operations ...    here we use mem_map_reserve() macro */ #include <linux/wrapper.h> /* needed for virt_to_phys() */ #include <asm/io.h> // virt_to_phys()#define DCCP_STAT_EXTERN#ifdef MODULE#include "compat.h"#include "queue.h"#include "dccp_tfrc.h"#include "dccp_tfrc_lookup.h"#include "dccp_tfrc_print.h"#else#include "dcp_super.h"#endif /* MODULE *///#define KERNEL_ASSERT_ON#ifdef KERNEL_ASSERT_ON#define KERNEL_ASSERT(expr)	if (!(expr)) 				   printk(KERN_DEBUG "KASSERT: %s:%d - Assertion failed! (%s) ",	   __FILE__, __LINE__, #expr)#else#define KERNEL_ASSERT(expr)#endif#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/time.h>#include <linux/timer.h>#include <linux/slab.h>#include <linux/string.h>#include <asm/semaphore.h>#include <net/sock.h>//#include <sys/param.h>//#include <sys/systm.h>//#include <sys/domain.h>//#include <sys/kernel.h>//#include <sys/lock.h>//#include <sys/malloc.h>//#include <sys/mbuf.h>//#include <sys/proc.h>//#include <sys/protosw.h>//#include <sys/signalvar.h>//#include <sys/socket.h>//#include <sys/socketvar.h>//#include <sys/sx.h>//#include <sys/sysctl.h>//#include <sys/syslog.h>//#include <net/if.h>//#include <net/route.h>//#include <netinet/in.h>//#include <netinet/in_systm.h>//#include <netinet/in_pcb.h>//#include <netinet/in_var.h>//#include <netinet/ip.h>//#include <netinet/ip_icmp.h>//#include <netinet/icmp_var.h>//#include <netinet/ip_var.h>//#include <netinet/dccp.h>//#include <netinet/dccp_var.h>#define LOG_INFO 1#define DCP_DEBUG 10 //outcommented by BJORN//#define TFRCDEBUG//#define TFRCDEBUGTIMERS/*#define NOTFRCSENDER#define NOTFRCRECV*///#define TFRC_DEBUG((LOG_INFO, (printk(#ifdef TFRCDEBUG#define TFRC_DEBUG(args) do_weird_debug args#else#define TFRC_DEBUG(args)#endif#ifdef TFRCDEBUGTIMERS#define TFRC_DEBUG_TIME(args) log args#else#define TFRC_DEBUG_TIME(args)#endif/* Timeval operations */const struct timeval delta_half = {0,TFRC_OPSYS_TIME_GRAN/2};/* * Half time value struct (accurate to +- 0.5us) * args:  tvp  -  pointer to timeval structure * Tested u:OK */#define HALFTIMEVAL(tvp) \do { \	if((tvp)->tv_sec & 1) \		(tvp)->tv_usec += 1000000; \			(tvp)->tv_sec = (tvp)->tv_sec >> 1; \			(tvp)->tv_usec = (tvp)->tv_usec >> 1; \}while(0)/* Sender side *//* Calculate new t_ipi (inter packet interval) by *    t_ipi = s/X_inst;  * args:  ccbp - pointer to sender ccb block * Tested u:OK - Note: No check for x=0 -> t_ipi ={0xFFF...,0xFFF} */#define CALCNEWTIPI(ccbp)                              \do{                                            \	ccbp->t_ipi.tv_sec = (long) ( ((double) (ccbp->s)) / (ccbp->x) );                    \		ccbp->t_ipi.tv_usec = (long) (( ((double)(ccbp->s)) / (ccbp->x) - ccbp->t_ipi.tv_sec)*((double)1000000.0));   \}while (0)/* Calculate new delta by  *    delta = min(t_ipi/2, t_gran/2); * args: ccbp - pointer to sender ccb block  * Tested u:OK */#define CALCNEWDELTA(ccbp)                             \do {                                          \	ccbp->delta = delta_half;                  \		if (ccbp->t_ipi.tv_sec == 0 && ccbp->t_ipi.tv_usec < TFRC_OPSYS_TIME_GRAN){     \			ccbp->delta = ccbp->t_ipi;              \				HALFTIMEVAL(&(ccbp->delta));            \		}                                          \} while (0)/******************************************************//* things that could be useful in a userspace program */#define SOCK_DCCP        6 		/* for api purposes */#define SOL_DCCP            269  #define SO_HANDSHAKE_DATA          1	/* sockopt */#define SO_ALLOW_HANDSHAKE_DATA    2/* the following is an optional struct for connect() or bind()..   if a normal sockaddr_in is used instead, a service of 0 is assumed.    accept() returns normal sockaddr_in's *//* service names should be supplied in network byte order */struct sockaddr_dcp{	struct sockaddr_in in;	unsigned int service;};/******************************************************/#define DCCP_PROTO 33#define DCP_INITIAL_CWND      3#define DCP_TIMEOUT          (2*HZ)	 	/* 2 second */#define DCP_MAX_TRIES         6	         /* really 6-1 = 5 */#define DCP_TIMEWAIT_LEN     (30*HZ)     /* 30 seconds */#define DCP_MIN_RTT          (HZ >> 3)   /* 1/8 of a second, that's 12 jiffies on i386 */#define DCP_RESPOND_TIMEOUT  (15*HZ)#define MAX_DCP_REQUEST_SZ    284#define DCP_NUMDUPACKS        3/* states */#define DCP_REQUESTING    1#define DCP_OPEN          2#define DCP_LISTENING     3#define DCP_RESPOND       4#define DCP_HALF_CLOSE    5#define DCP_TIMEWAIT      6#define DCP_CLOSED        7		/* same as TCP_CLOSE, don't change value */#define TYPE_REQUEST     0x00#define TYPE_RESPONSE    0x10#define TYPE_DATA        0x20#define TYPE_ACK         0x30#define TYPE_DATAACK     0x40#define TYPE_CLOSEREQ    0x50#define TYPE_CLOSE       0x60#define TYPE_RESET       0x70#define TYPE_MOVE        0x80#define TYPE_INVALID     0xF0#define DCP_OPT_PAD      00#define DCP_OPT_DISCARD  01#define DCP_OPT_IGNORED  32#define DCP_OPT_ASK      33#define DCP_OPT_CHOOSE   34#define DCP_OPT_ANSWER   35#define DCP_OPT_ICOOKIE  36#define DCP_OPT_ACKV0    37#define DCP_OPT_ACKV1    38#define DCP_OPT_RBDROP   39#define DCP_OPT_TS       40#define DCP_OPT_TS_ECHO  41#define DCP_OPT_MOBILE   42#define DCP_OPT_BCD      43#define DCP_OPT_WINCOUNT 128       /* Used for DCCP CCID 3 */#define DCP_OPT_ELAPTIME 193#define DCP_OPT_LOSSEVENT 192#define DCP_OPT_RECEIVERATE 194    /* END USED FOR DCCP CCID 3 */#define DCP_OPT_LOSSINTER 195      /* included for completeness will not be used */#define DCP_OPT_STATE_KNOWN  1#define DCP_OPT_STATE_ASKING 2#define DCP_OPT_STATE_ANS    3#define DCP_NEG_TYPE_CC        1#define DCP_NEG_TYPE_ECN       2#define DCP_NEG_TYPE_ACKRATIO  3#define DCP_NEG_TYPE_ACKVECTOR 4#define WHOAMI_UNKNOWN 0#define WHOAMI_CLIENT  1#define WHOAMI_SERVER  2#define WHOAMI_BINDER  3#define FLAG_ACKSCHED               0x01#define FLAG_ALLOW_LOADED_HANDSHAKE 0x02#define DCCP_PORT_BASE  1025#define DCCP_PORT_RANGE 16000#define DCCP_PORT_HI    (DCCP_PORT_BASE + DCCP_PORT_RANGE)#define DCP_SK_HASH_SZ 863#define INIT_VECTOR_SIZE 512 /* keep as a multiple of 8!! *//* datatypes *//* Used to store an outgoing packet in the right format for ip_build_xmit * * Fields:	h - the DCCP header (including headers) of the packet * 		kdb - the handshake data (for connection handshake packets only),  // kdb stands for Kernel Data Block?? - SHANE * 		hl - the length of the DCCP header * 		kdbl - the length of the handshake data * 		iov - the io vector containing the data portion of the packet (except when we're in connection handshake) * 		check - the checksum for the future IP packet? We set it to zero as checksum calc for IP will come later * */struct build_t{	unsigned char *h,*kdb;	u16 hl,kdbl;	struct iovec *iov;	u32 check;};/* Describes a DCCP socket * * Fields:	sk - the actual socket structure itself * 		locala - the address of the local end of the connection * 		remotea - the address of the remote end of the connection * 		svc - the service code * 		lp - the local port number for the connection * 		rp - the remote port number for the connection * 		p - the previous entry in the DCCP socket list * 		n - the next entry in the DCCP socket list * */struct dccp_sk_list_t{	struct sock *sk;	u32 locala, remotea, svc;	u16 lp, rp;	struct dccp_sk_list_t *p, *n;};/* Used to represent an outgoing ACK that is acknowledging previously received ACKs, rather than incoming data * * Fields:	localseq - the sequence number of the outgoing ACK * 		ackthru - the acknowledgement number of the outgoing ACK * 		next - the next member of the clist * */struct ack_collapse_t{	u32 localseq, ackthru;	struct ack_collapse_t *next;};/* global allocations - mostly counters and locks */static struct dccp_sk_list_t *dccp_sk_hash[DCP_SK_HASH_SZ];static spinlock_t dccp_port_lock;static spinlock_t dccp_reset_lock;static u16 dccp_port;static rwlock_t dccp_table_lock[16];static unsigned char dccp_port_map[DCCP_PORT_RANGE/8+1];static kmem_cache_t *dccp_slab, *dccp_slab_sk, *dccp_slab_ack;/* *sk used for resets when no connection exists */static struct inode reset_inode;static struct socket *reset_socket = &reset_inode.u.socket_i;static struct tq_struct itask;/* prototypes */static void dccp_reset (struct sock *sk, u32 reason);static void dccp_send_close (struct sock *sk, unsigned char close_or_closeR);static int unregister_dccp_sk (struct sock *sk);static void dccp_port_release (u16 i);static int dccp_port_claim (u16 i);static inline void dccp_update_ackn (unsigned int *t, struct sk_buff *skb);static inline void new_rtt_sample (struct dcp_opt *tp, u16 M);static int credit_pkt (struct sock *sk, u32 sn);static inline int increment_ackvector (struct sock *sk, u32 sn);static u32 dccp_whatis_ackn (struct sk_buff *skb);static void dccp_write_24 (u32 *s, char *d, int inc);static inline unsigned char dcp_write_ndp (u16 *ndp, int inc);static unsigned char *dccp_generate_ackvector (struct sock *sk, int *l);static int dccp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen) ;static inline int  check_clist (struct dcp_opt *tp, u32 sn);void inet_sock_release(struct sock *sk);static void dccp_half_closed (void *vsk);static u16 dccp_parse_option (struct sk_buff *skb, unsigned char option,u16 *ics);static void generic_option_negotiation (struct dcp_opt *tp);static inline void rcvr_ratio_inbounds (struct dcp_opt *tp);static inline unsigned char value_in_ackvector (struct sock *sk, u32 sn);static void  dccp_schedule_ack (void *vsk);/* External declarations */extern int dccp_get_option(char *, int, int, char *,int);/* Forward declarations */void  tfrc_time_no_feedback(void *ccb);void  tfrc_time_send(void *ccb);void  tfrc_set_send_timer(struct tfrc_send_ccb *cb, struct timeval t_now);void  tfrc_updateX(struct tfrc_send_ccb *cb, struct timeval t_now);double tfrc_calcX(u_int16_t s, u_int32_t R, double p);void  tfrc_send_term(void *ccb);/* Forward declarations */double tfrc_calcImean(struct tfrc_recv_ccb *cb);void tfrc_recv_send_feedback(struct tfrc_recv_ccb *cb);int tfrc_recv_add_hist(struct tfrc_recv_ccb *cb, struct r_hist_entry *packet);void tfrc_recv_detectLoss(struct tfrc_recv_ccb *cb);u_int32_t tfrc_recv_calcFirstLI(struct tfrc_recv_ccb *cb);void tfrc_recv_updateLI(struct tfrc_recv_ccb *cb, long seq_loss, u_int8_t win_loss);void *tfrc_recv_init(struct dccpcb *pcb);void *tfrc_send_init(struct dccpcb* pcb);void tfrc_send_packet_recv(void *ccb, char *options, int optlen);void tfrc_recv_packet_recv(void *ccb, char *options, int optlen);void tfrc_send_free(void *ccb);void tfrc_recv_free(void *ccb);int tfrc_send_packet(void *ccb, long datasize);void tfrc_send_packet_sent(void *ccb, int moreToSend, long datasize);/* Weights used to calculate loss event rate */const double tfrc_recv_w[] = {1, 1, 1, 1, 0.8, 0.6, 0.4, 0.2};/* macros *//* Find a data packet in history * args:  cb - ccb of receiver *        elm - pointer to element (variable) *        num - number in history (variable) * returns:  elm points to found packet, otherwise NULL * Tested u:OK */#define TFRC_RECV_FINDDATAPACKET(cb,elm,num) \do{ \	elm = STAILQ_FIRST(&((cb)->hist)); \		while((elm) != NULL){ \			if((elm)->type == DCCP_TYPE_DATA || (elm)->type == DCCP_TYPE_DATAACK) \				(num)--; \					if(num == 0) \						break; \							elm = STAILQ_NEXT((elm), linfo); \		} \} while (0)/* Find next data packet in history * args:  cb - ccb of receiver *        elm - pointer to element (variable) * returns:  elm points to found packet, otherwise NULL * Tested u:OK */#define TFRC_RECV_NEXTDATAPACKET(cb,elm) \do{ \	if(elm != NULL){ \		elm = STAILQ_NEXT(elm, linfo); \			while((elm) != NULL && (elm)->type != DCCP_TYPE_DATA && (elm)->type != DCCP_TYPE_DATAACK){ \				elm = STAILQ_NEXT((elm), linfo); \			} \	} \} while (0)#define DCP_DATA_EVENT         (tp->rcvq_h != tp->rcvq_t)#define DCP_DATA_EVENT_TO      ((tp->rcvq_h != tp->rcvq_t) || tp->timer_expired)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -