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

📄 tcpsp_conn.c

📁 在传输层实现了资源的负载平衡 实现了集群
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct rtable *rt;			/* Route to the other host */	struct iphdr  *iph = skb->nh.iph;	u8     tos = iph->tos;	int    mtu;	EnterFunction(7);	if (ip_route_output(&rt, iph->daddr, 0, RT_TOS(tos), 0)) {		TCPSP_DBG_RL("tcpsp_xmit(): ip_route_output error, "			     "dest: %u.%u.%u.%u\n", NIPQUAD(iph->daddr));		goto tx_error_icmp;	}	/* MTU checking ??? */	mtu = rt->u.dst.pmtu;	if ((skb->len > mtu) && (iph->frag_off&__constant_htons(IP_DF))) {		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));		ip_rt_put(rt);		TCPSP_DBG_RL("tcpsp_xmit(): frag needed\n");		goto tx_error;	}	/* drop old route */	dst_release(skb->dst);	skb->dst = &rt->u.dst;#ifdef CONFIG_NETFILTER_DEBUG	skb->nf_debug = 1 << NF_IP_LOCAL_OUT;#endif /* CONFIG_NETFILTER_DEBUG */	ip_send(skb);	LeaveFunction(7);	return NF_STOLEN;  tx_error_icmp:	dst_link_failure(skb);  tx_error:	kfree_skb(skb);	return NF_STOLEN;}/* *  Bind a connection entry with the corresponding packet_xmit. *  Called by tcpsp_conn_new. */static inline void tcpsp_bind_xmit(struct tcpsp_conn *cp){	cp->packet_xmit = tcpsp_xmit;}static inline voidtcpsp_timeout_attach(struct tcpsp_conn *cp, struct tcpsp_timeout_table *tt){	atomic_inc(&tt->refcnt);	cp->timeout_table = tt;}static inline void tcpsp_timeout_detach(struct tcpsp_conn *cp){	struct tcpsp_timeout_table *tt = cp->timeout_table;	if (!tt)		return;	cp->timeout_table = NULL;	atomic_dec(&tt->refcnt);}static void tcpsp_conn_expire(unsigned long data){	struct tcpsp_conn *cp = (struct tcpsp_conn *)data;	if (cp->timeout_table)		cp->timeout = cp->timeout_table->timeout[TCPSP_S_TIME_WAIT];	else		cp->timeout = tcpsp_timeout_tbl.timeout[TCPSP_S_TIME_WAIT];	/*	 *	hey, I'm using it	 */	atomic_inc(&cp->refcnt);	/*	 *	unhash it if it is hashed in the conn table	 */	tcpsp_conn_unhash(cp);	/*	 *	refcnt==1 implies I'm the only one referrer	 */	if (atomic_read(&cp->refcnt) == 1) {		/* make sure that there is no timer on it now */		if (timer_pending(&cp->timer))			del_timer(&cp->timer);		tcpsp_timeout_detach(cp);		atomic_dec(&tcpsp_conn_count);		kmem_cache_free(tcpsp_conn_cachep, cp);		return;	}	TCPSP_DBG(5, "delayed: refcnt-1=%d\n", atomic_read(&cp->refcnt)-1);	tcpsp_conn_put(cp);}static inline void fill_conn_tuple(struct conn_tuple *t, struct sock *sk){	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);	t->laddr = sk->rcv_saddr;	t->lport = sk->sport;	t->raddr = sk->daddr;	t->rport = sk->dport;	t->splice_iss = tp->snd_nxt;	t->splice_irs = tp->rcv_nxt;	t->splice_tsv = tp->rcv_tsval;	t->splice_tse = tp->rcv_tsecr;	t->timestamp_ok = tp->tstamp_ok;}/* *  Create and hash a new tcpsp into the tcpsp_conn_tabs. */struct tcpsp_conn *tcpsp_conn_new(struct socket *sock1, struct socket *sock2, int n){	struct tcp_opt *tp1, *tp2;	struct tcpsp_conn *cp;	cp = kmem_cache_alloc(tcpsp_conn_cachep, GFP_ATOMIC);	if (cp == NULL) {		TCPSP_ERR_RL("tcpsp_conn_new: no memory available.\n");		return NULL;	}	memset(cp, 0, sizeof(*cp));	cp->lock = SPIN_LOCK_UNLOCKED;	init_timer(&cp->timer);	cp->timer.data = (unsigned long) cp;	cp->timer.function = tcpsp_conn_expire;	tcpsp_timeout_attach(cp, &tcpsp_timeout_tbl);	cp->socket[0] = sock1;	cp->socket[1] = sock2;	atomic_set(&cp->need_rst, 1);	fill_conn_tuple(&cp->conn[0], sock1->sk);	fill_conn_tuple(&cp->conn[1], sock2->sk);	cp->conn[1].splice_iss += n;	atomic_inc(&tcpsp_conn_count);	/* Set its state and timeout */	if (sock1->sk->state == TCP_ESTABLISHED	    && sock2->sk->state == TCP_ESTABLISHED)		set_state_timeout(cp, TCPSP_S_ESTABLISHED);	else /* probably need to consider other states here */		set_state_timeout(cp, TCPSP_S_NONE);	/* Bind its packet transmitter */	tcpsp_bind_xmit(cp);	atomic_set(&cp->refcnt, 1);	/* Hash it in the tcpsp_conn_tab finally */	tcpsp_conn_hash(cp);	tp1 = &(sock1->sk->tp_pinfo.af_tcp);	tp2 = &(sock2->sk->tp_pinfo.af_tcp);	TCPSP_DBG(5, "sock1: rcv_nxt %u snd_nxt %u snd_una %u\n",		  tp1->rcv_nxt, tp1->snd_nxt, tp1->snd_una);	TCPSP_DBG(5, "sock2: rcv_nxt %u snd_nxt %u snd_una %u\n",		  tp2->rcv_nxt, tp2->snd_nxt, tp2->snd_una);	TCPSP_DBG(5, "sock2: iss %u  irs %u\n",		  cp->conn[1].splice_iss, cp->conn[1].splice_irs);	return cp;}/* *	/proc/net/tcpsp_conn entries */static inttcpsp_conn_getinfo(char *buffer, char **start, off_t offset, int length){	off_t pos=0;	int idx, len=0;	char temp[70];	struct tcpsp_conn *cp;	struct list_head *l, *e;	pos = 128;	if (pos > offset) {		len += sprintf(buffer+len, "%-127s\n",			       "FromIP   FPrt ToIP     TPrt LocalIP  LPrt DestIP   DPrt State       Expires");	}	for(idx = 0; idx < TCPSP_CONN_TAB_SIZE; idx++) {		/*		 *	Lock is actually only need in next loop		 *	we are called from uspace: must stop bh.		 */		read_lock_bh(&tcpsp_conn_lock);		l = &tcpsp_conn_tab1[idx];		for (e=l->next; e!=l; e=e->next) {			cp = list_entry(e, struct tcpsp_conn, f_list);			pos += 128;			if (pos <= offset)				continue;			sprintf(temp,				"%08X %04X %08X %04X %08X %04X %08X %04X %-11s %7lu",				ntohl(cp->conn[0].raddr),				ntohs(cp->conn[0].rport),				ntohl(cp->conn[0].laddr),				ntohs(cp->conn[0].lport),				ntohl(cp->conn[1].laddr),				ntohs(cp->conn[1].lport),				ntohl(cp->conn[1].raddr),				ntohs(cp->conn[1].rport),				tcpsp_state_name(cp->state),				cp->timer.expires-jiffies);			len += sprintf(buffer+len, "%-127s\n", temp);			if (pos >= offset+length) {				read_unlock_bh(&tcpsp_conn_lock);				goto done;			}		}		read_unlock_bh(&tcpsp_conn_lock);	}  done:	*start = buffer+len-(pos-offset);       /* Start of wanted data */	len = pos-offset;	if (len > length)		len = length;	if (len < 0)		len = 0;	return len;}/* *      Flush all the connection entries in the tcpsp_conn_tab */static void tcpsp_conn_flush(void){	int idx;	struct list_head *list;	struct tcpsp_conn *cp;  flush_again:	for (idx=0; idx<TCPSP_CONN_TAB_SIZE; idx++) {		/*		 *  Lock is actually needed in this loop.		 */		write_lock_bh(&tcpsp_conn_lock);		list = &tcpsp_conn_tab1[idx];		while (!list_empty(list)) {			cp = list_entry(list->next, struct tcpsp_conn, f_list);			TCPSP_DBG(4, "delete the spliced connection\n");			if (del_timer(&cp->timer)) {				write_unlock(&tcpsp_conn_lock);				tcpsp_conn_expire_now(cp);				write_lock(&tcpsp_conn_lock);			}		}		write_unlock_bh(&tcpsp_conn_lock);	}	/* the counter may be not NULL, because maybe some conn entries	   are run by slow timer handler or unhashed but still referred */	if (atomic_read(&tcpsp_conn_count) != 0) {		schedule();		goto flush_again;	}}int tcpsp_conn_init(void){	int idx;	/*	 * Allocate the connection hash table and initialize its list heads	 */	if (!(tcpsp_conn_tab1 =	      vmalloc(TCPSP_CONN_TAB_SIZE * sizeof(struct list_head))))		return -ENOMEM;	if (!(tcpsp_conn_tab2 =	      vmalloc(TCPSP_CONN_TAB_SIZE * sizeof(struct list_head)))) {		vfree(tcpsp_conn_tab1);		return -ENOMEM;	}	/* Allocate tcpsp_conn slab cache */	tcpsp_conn_cachep = kmem_cache_create("tcpsp_conn",					      sizeof(struct tcpsp_conn), 0,					      SLAB_HWCACHE_ALIGN, NULL, NULL);	if (!tcpsp_conn_cachep) {		vfree(tcpsp_conn_tab1);		vfree(tcpsp_conn_tab2);		return -ENOMEM;	}	TCPSP_INFO("Connection hash table configured "		   "(size=%d, memory=%ldKbytes)\n",		   TCPSP_CONN_TAB_SIZE,		   (long)(TCPSP_CONN_TAB_SIZE*sizeof(struct list_head))/1024);	TCPSP_DBG(0, "Each connection entry needs %d bytes at least\n",		  sizeof(struct tcpsp_conn));	for (idx = 0; idx < TCPSP_CONN_TAB_SIZE; idx++) {		INIT_LIST_HEAD(&tcpsp_conn_tab1[idx]);		INIT_LIST_HEAD(&tcpsp_conn_tab2[idx]);	}	proc_net_create("tcpsp_conn", 0, tcpsp_conn_getinfo);	return 0;}void tcpsp_conn_cleanup(void){	/* flush all the connection entries first */	tcpsp_conn_flush();	/* Release the empty cache */	kmem_cache_destroy(tcpsp_conn_cachep);	proc_net_remove("tcpsp_conn");	vfree(tcpsp_conn_tab1);	vfree(tcpsp_conn_tab2);}

⌨️ 快捷键说明

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