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

📄 hdlc_fr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			stats->tx_bytes += skb->len;			stats->tx_packets++;			if (pvc->state.fecn) /* TX Congestion counter */				stats->tx_compressed++;			skb->dev = pvc->frad;			dev_queue_xmit(skb);			return 0;		}	}	stats->tx_dropped++;	dev_kfree_skb(skb);	return 0;}static int pvc_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < 68) || (new_mtu > HDLC_MAX_MTU))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static inline void fr_log_dlci_active(pvc_device *pvc){	printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",	       pvc->frad->name,	       pvc->dlci,	       pvc->main ? pvc->main->name : "",	       pvc->main && pvc->ether ? " " : "",	       pvc->ether ? pvc->ether->name : "",	       pvc->state.new ? " new" : "",	       !pvc->state.exist ? "deleted" :	       pvc->state.active ? "active" : "inactive");}static inline u8 fr_lmi_nextseq(u8 x){	x++;	return x ? x : 1;}static void fr_lmi_send(struct net_device *dev, int fullrep){	hdlc_device *hdlc = dev_to_hdlc(dev);	struct sk_buff *skb;	pvc_device *pvc = state(hdlc)->first_pvc;	int lmi = state(hdlc)->settings.lmi;	int dce = state(hdlc)->settings.dce;	int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;	int stat_len = (lmi == LMI_CISCO) ? 6 : 3;	u8 *data;	int i = 0;	if (dce && fullrep) {		len += state(hdlc)->dce_pvc_count * (2 + stat_len);		if (len > HDLC_MAX_MRU) {			printk(KERN_WARNING "%s: Too many PVCs while sending "			       "LMI full report\n", dev->name);			return;		}	}	skb = dev_alloc_skb(len);	if (!skb) {		printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n",		       dev->name);		return;	}	memset(skb->data, 0, len);	skb_reserve(skb, 4);	if (lmi == LMI_CISCO) {		skb->protocol = __constant_htons(NLPID_CISCO_LMI);		fr_hard_header(&skb, LMI_CISCO_DLCI);	} else {		skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI);		fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);	}	data = skb_tail_pointer(skb);	data[i++] = LMI_CALLREF;	data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY;	if (lmi == LMI_ANSI)		data[i++] = LMI_ANSI_LOCKSHIFT;	data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :		LMI_ANSI_CISCO_REPTYPE;	data[i++] = LMI_REPT_LEN;	data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;	data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;	data[i++] = LMI_INTEG_LEN;	data[i++] = state(hdlc)->txseq =		fr_lmi_nextseq(state(hdlc)->txseq);	data[i++] = state(hdlc)->rxseq;	if (dce && fullrep) {		while (pvc) {			data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :				LMI_ANSI_CISCO_PVCSTAT;			data[i++] = stat_len;			/* LMI start/restart */			if (state(hdlc)->reliable && !pvc->state.exist) {				pvc->state.exist = pvc->state.new = 1;				fr_log_dlci_active(pvc);			}			/* ifconfig PVC up */			if (pvc->open_count && !pvc->state.active &&			    pvc->state.exist && !pvc->state.new) {				pvc_carrier(1, pvc);				pvc->state.active = 1;				fr_log_dlci_active(pvc);			}			if (lmi == LMI_CISCO) {				data[i] = pvc->dlci >> 8;				data[i + 1] = pvc->dlci & 0xFF;			} else {				data[i] = (pvc->dlci >> 4) & 0x3F;				data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80;				data[i + 2] = 0x80;			}			if (pvc->state.new)				data[i + 2] |= 0x08;			else if (pvc->state.active)				data[i + 2] |= 0x02;			i += stat_len;			pvc = pvc->next;		}	}	skb_put(skb, i);	skb->priority = TC_PRIO_CONTROL;	skb->dev = dev;	skb_reset_network_header(skb);	dev_queue_xmit(skb);}static void fr_set_link_state(int reliable, struct net_device *dev){	hdlc_device *hdlc = dev_to_hdlc(dev);	pvc_device *pvc = state(hdlc)->first_pvc;	state(hdlc)->reliable = reliable;	if (reliable) {		netif_dormant_off(dev);		state(hdlc)->n391cnt = 0; /* Request full status */		state(hdlc)->dce_changed = 1;		if (state(hdlc)->settings.lmi == LMI_NONE) {			while (pvc) {	/* Activate all PVCs */				pvc_carrier(1, pvc);				pvc->state.exist = pvc->state.active = 1;				pvc->state.new = 0;				pvc = pvc->next;			}		}	} else {		netif_dormant_on(dev);		while (pvc) {		/* Deactivate all PVCs */			pvc_carrier(0, pvc);			pvc->state.exist = pvc->state.active = 0;			pvc->state.new = 0;			if (!state(hdlc)->settings.dce)				pvc->state.bandwidth = 0;			pvc = pvc->next;		}	}}static void fr_timer(unsigned long arg){	struct net_device *dev = (struct net_device *)arg;	hdlc_device *hdlc = dev_to_hdlc(dev);	int i, cnt = 0, reliable;	u32 list;	if (state(hdlc)->settings.dce) {		reliable = state(hdlc)->request &&			time_before(jiffies, state(hdlc)->last_poll +				    state(hdlc)->settings.t392 * HZ);		state(hdlc)->request = 0;	} else {		state(hdlc)->last_errors <<= 1; /* Shift the list */		if (state(hdlc)->request) {			if (state(hdlc)->reliable)				printk(KERN_INFO "%s: No LMI status reply "				       "received\n", dev->name);			state(hdlc)->last_errors |= 1;		}		list = state(hdlc)->last_errors;		for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1)			cnt += (list & 1);	/* errors count */		reliable = (cnt < state(hdlc)->settings.n392);	}	if (state(hdlc)->reliable != reliable) {		printk(KERN_INFO "%s: Link %sreliable\n", dev->name,		       reliable ? "" : "un");		fr_set_link_state(reliable, dev);	}	if (state(hdlc)->settings.dce)		state(hdlc)->timer.expires = jiffies +			state(hdlc)->settings.t392 * HZ;	else {		if (state(hdlc)->n391cnt)			state(hdlc)->n391cnt--;		fr_lmi_send(dev, state(hdlc)->n391cnt == 0);		state(hdlc)->last_poll = jiffies;		state(hdlc)->request = 1;		state(hdlc)->timer.expires = jiffies +			state(hdlc)->settings.t391 * HZ;	}	state(hdlc)->timer.function = fr_timer;	state(hdlc)->timer.data = arg;	add_timer(&state(hdlc)->timer);}static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb){	hdlc_device *hdlc = dev_to_hdlc(dev);	pvc_device *pvc;	u8 rxseq, txseq;	int lmi = state(hdlc)->settings.lmi;	int dce = state(hdlc)->settings.dce;	int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;	if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :			LMI_CCITT_CISCO_LENGTH)) {		printk(KERN_INFO "%s: Short LMI frame\n", dev->name);		return 1;	}	if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :			     NLPID_CCITT_ANSI_LMI)) {		printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",		       dev->name);		return 1;	}	if (skb->data[4] != LMI_CALLREF) {		printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",		       dev->name, skb->data[4]);		return 1;	}	if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {		printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",		       dev->name, skb->data[5]);		return 1;	}	if (lmi == LMI_ANSI) {		if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {			printk(KERN_INFO "%s: Not ANSI locking shift in LMI"			       " message (0x%02X)\n", dev->name, skb->data[6]);			return 1;		}		i = 7;	} else		i = 6;	if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :			     LMI_ANSI_CISCO_REPTYPE)) {		printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",		       dev->name, skb->data[i]);		return 1;	}	if (skb->data[++i] != LMI_REPT_LEN) {		printk(KERN_INFO "%s: Invalid LMI Report type IE length"		       " (%u)\n", dev->name, skb->data[i]);		return 1;	}	reptype = skb->data[++i];	if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {		printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",		       dev->name, reptype);		return 1;	}	if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :			       LMI_ANSI_CISCO_ALIVE)) {		printk(KERN_INFO "%s: Not an LMI Link integrity verification"		       " IE (0x%02X)\n", dev->name, skb->data[i]);		return 1;	}	if (skb->data[++i] != LMI_INTEG_LEN) {		printk(KERN_INFO "%s: Invalid LMI Link integrity verification"		       " IE length (%u)\n", dev->name, skb->data[i]);		return 1;	}	i++;	state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */	rxseq = skb->data[i++];	/* Should confirm our sequence */	txseq = state(hdlc)->txseq;	if (dce)		state(hdlc)->last_poll = jiffies;	error = 0;	if (!state(hdlc)->reliable)		error = 1;	if (rxseq == 0 || rxseq != txseq) { /* Ask for full report next time */		state(hdlc)->n391cnt = 0;		error = 1;	}	if (dce) {		if (state(hdlc)->fullrep_sent && !error) {/* Stop sending full report - the last one has been confirmed by DTE */			state(hdlc)->fullrep_sent = 0;			pvc = state(hdlc)->first_pvc;			while (pvc) {				if (pvc->state.new) {					pvc->state.new = 0;/* Tell DTE that new PVC is now active */					state(hdlc)->dce_changed = 1;				}				pvc = pvc->next;			}		}		if (state(hdlc)->dce_changed) {			reptype = LMI_FULLREP;			state(hdlc)->fullrep_sent = 1;			state(hdlc)->dce_changed = 0;		}		state(hdlc)->request = 1; /* got request */		fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);		return 0;	}	/* DTE */	state(hdlc)->request = 0; /* got response, no request pending */	if (error)		return 0;	if (reptype != LMI_FULLREP)		return 0;	pvc = state(hdlc)->first_pvc;	while (pvc) {		pvc->state.deleted = 1;		pvc = pvc->next;	}	no_ram = 0;	while (skb->len >= i + 2 + stat_len) {		u16 dlci;		u32 bw;		unsigned int active, new;		if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :				       LMI_ANSI_CISCO_PVCSTAT)) {			printk(KERN_INFO "%s: Not an LMI PVC status IE"			       " (0x%02X)\n", dev->name, skb->data[i]);			return 1;		}		if (skb->data[++i] != stat_len) {			printk(KERN_INFO "%s: Invalid LMI PVC status IE length"			       " (%u)\n", dev->name, skb->data[i]);			return 1;		}		i++;		new = !! (skb->data[i + 2] & 0x08);		active = !! (skb->data[i + 2] & 0x02);		if (lmi == LMI_CISCO) {			dlci = (skb->data[i] << 8) | skb->data[i + 1];			bw = (skb->data[i + 3] << 16) |				(skb->data[i + 4] << 8) |				(skb->data[i + 5]);		} else {			dlci = ((skb->data[i] & 0x3F) << 4) |				((skb->data[i + 1] & 0x78) >> 3);			bw = 0;		}		pvc = add_pvc(dev, dlci);		if (!pvc && !no_ram) {			printk(KERN_WARNING			       "%s: Memory squeeze on fr_lmi_recv()\n",			       dev->name);			no_ram = 1;		}		if (pvc) {			pvc->state.exist = 1;			pvc->state.deleted = 0;			if (active != pvc->state.active ||			    new != pvc->state.new ||			    bw != pvc->state.bandwidth ||			    !pvc->state.exist) {				pvc->state.new = new;				pvc->state.active = active;				pvc->state.bandwidth = bw;				pvc_carrier(active, pvc);				fr_log_dlci_active(pvc);			}		}		i += stat_len;	}	pvc = state(hdlc)->first_pvc;	while (pvc) {		if (pvc->state.deleted && pvc->state.exist) {			pvc_carrier(0, pvc);			pvc->state.active = pvc->state.new = 0;			pvc->state.exist = 0;			pvc->state.bandwidth = 0;			fr_log_dlci_active(pvc);		}		pvc = pvc->next;	}

⌨️ 快捷键说明

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