文档章节

TCP/IP协议详解卷2 第4章 以太网

卜星星
 卜星星
发布于 2015/03/02 11:49
字数 811
阅读 82
收藏 1

        这一章说是要介绍:以太网设备驱动程序在初始化后是如何接收和传输帧的;还有配置网络通用ioctl。

在ifnet中有7个函数:

/* 这是初始化等处理函数,这些函数就是我们访问网络设备驱动程序 */ 
  int  (*if_init)   __P(( int ));
  int  (*if_output)  __P(( struct  ifnet *,  struct  mbuf *,  struct  sockaddr *,   struct  rtentry *));
  int  (*if_start)  __P(( struct  ifnet *));
  int  (*if_done)  __P(( struct  ifnet *)); 
  int  (*if_ioctl)  __P(( struct  ifnet *, u_long, caddr_t));
  int  (*if_reset)  __P(( int ));  
  int  (*if_watchdog)  __P(( int )); 

这7个函数就是用来调用驱动程序的。不同设备都有不同的驱动函数,比如这里说的以太网那个if_output就是ether_output

SNMP:简单网络管理协议信息库(SNMP MIB-II)

以太网封闭结构:目标地址(6) 源地址(6)协议类型(2) 共14字节  46~1500数据  CRC(4)

当设备接收到一个以太网帧,并且完整可用时,就产生中断,调用leintr,leintr调用leread把帧从接口弄到mbuf中,

所以以太网设备驱动程序将接收到的帧传给ether_input处理

leread函数第一个参数unit就是在ifnet中的那个if_unit同一类接口不同编号

leread(unit, buf, len)
 int unit;
 char *buf;
 int len;
{
 register struct le_softc *le = &le_softc[unit];
 register struct ether_header *et;
     struct mbuf *m;
 int off, resid, flags;
 le->sc_if.if_ipackets++;
 et = (struct ether_header *)buf;
 et->ether_type = ntohs((u_short)et->ether_type);
 /* adjust input length to account for header and CRC */
 len = len - sizeof(struct ether_header) - 4;
#define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
 if (et->ether_type >= ETHERTYPE_TRAIL &&
     et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
  off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
  if (off >= ETHERMTU)
   return;  /* sanity */
  et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
  resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
  if (off + resid > len)
   return;  /* sanity */
  len = off + resid;
 } else
  off = 0;
 if (len <= 0) {
  if (ledebug)
   log(LOG_WARNING,
       "le%d: ierror(runt packet): from %s: len=%d\n",
       unit, ether_sprintf(et->ether_shost), len);
  le->sc_runt++;
  le->sc_if.if_ierrors++;
  return;
 }
 flags = 0;
 if (bcmp((caddr_t)etherbroadcastaddr,
     (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
  flags |= M_BCAST;
 if (et->ether_dhost[0] & 1)
  flags |= M_MCAST;
#if NBPFILTER > 0
 /*
  * Check if there's a bpf filter listening on this interface.
  * If so, hand off the raw packet to enet.
  */
 if (le->sc_if.if_bpf) {
  bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header));
  /*
   * Keep the packet if it's a broadcast or has our
   * physical ethernet address (or if we support
   * multicast and it's one).
   */
  if (
#ifdef MULTICAST
      (flags & (M_BCAST | M_MCAST)) == 0 &&
#else
      (flags & M_BCAST) == 0 &&
#endif
      bcmp(et->ether_dhost, le->sc_addr,
   sizeof(et->ether_dhost)) != 0)
   return;
 }
#endif
 /*
  * Pull packet off interface.  Off is nonzero if packet
  * has trailing header; m_devget will then force this header
  * information to be at the front, but we still have to drop
  * the type and length which are at the front of any trailer data.
  */
 m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0);
 if (m == 0)
  return;
 m->m_flags |= flags;
 ether_input(&le->sc_if, et, m);
}
void
ether_input(ifp, eh, m)
 struct ifnet *ifp;
 register struct ether_header *eh;
 struct mbuf *m;
{
 register struct ifqueue *inq;
 register struct llc *l;
 struct arpcom *ac = (struct arpcom *)ifp;
 int s;
 if ((ifp->if_flags & IFF_UP) == 0) {
  m_freem(m);
  return;
 }
 ifp->if_lastchange = time;
 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
     sizeof(etherbroadcastaddr)) == 0)
  m->m_flags |= M_BCAST;
 else if (eh->ether_dhost[0] & 1)
  m->m_flags |= M_MCAST;
 if (m->m_flags & (M_BCAST|M_MCAST))
  ifp->if_imcasts++;
 switch (eh->ether_type) {
#ifdef INET
 case ETHERTYPE_IP:
  schednetisr(NETISR_IP);
  inq = &ipintrq;
  break;
 case ETHERTYPE_ARP:
  schednetisr(NETISR_ARP);
  inq = &arpintrq;
  break;
#endif

  default:
  if (eh->ether_type > ETHERMTU) {
    m_freem(m);
    return;
  } 
 
/* 下面很多都忽略掉了只留下了INET的 */
 }
 s = splimp();
 if (IF_QFULL(inq)) {
  IF_DROP(inq);
  m_freem(m);
 } else
  IF_ENQUEUE(inq, m);
 splx(s);
}

由于我其实也不知道究竟要看什么,哪些是有用的,哪些没有用,所以只能从头看下去,争取能看完一遍,之后再回来总结一下。

© 著作权归作者所有

共有 人打赏支持
卜星星
粉丝 27
博文 111
码字总数 68736
作品 0
海淀
程序员
《TCP/IP详解.卷1:协议》读书笔记

从大学的时候就听余老师介绍过stevens这三卷书,还听说最后一卷没写完作者就去世了,工作后也一直听人谈起, 但还是没去真正读它。最近因为工作上很多涉及到网络,捉包,各种tcpdump的使用,...

suit
2014/10/21
0
0
网络编程懒人入门(三):快速理解TCP协议一篇就够

原作者:阮一峰(ruanyifeng.com),本文由即时通讯网重新整理发布,感谢原作者的无私分享。 1、前言 本系列文章的前两篇《网络编程懒人入门(一):快速理解网络通信协议(上篇)》、《网络编程...

JackJiang2011
2017/10/12
0
0
TCP/IP详解卷一概述

第1章 概述 1.1 引言 很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但TCP/IP协议族允许它们互相进行通信。这一点很让人感到吃惊,因为它的作用已远远超出了起初的设想。...

Junin
2012/07/31
0
0
TCP/IP详解(一)

TCP/IP详解(一) 1 概述 1.1 引言 很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但TCP/IP协议组件允许它们互相进行通信。这一点很让人感到吃惊,因为它的作用已远远超...

红薯
2009/05/05
1K
2
APR协议分组格式的字段解释

在看《TCP/IP详解 卷1》的第四章APR协议的时候,看到APR请求和应答分组格式里的字段如下图: 其中前两个字段和倒数第4个字段,倒数第2个字段有什么区别吗? 这本书里的解释我没有看明白,解释...

xinspace
2013/04/10
287
1

没有更多内容

加载失败,请刷新页面

加载更多

搬瓦工镜像站bwh1.net被DNS污染,国内打不开搬瓦工官网

今天下午(2018年10月17日),继搬瓦工主域名bandwagonhost.com被污染后,这个国内的镜像地址bwh1.net也被墙了。那么目前应该怎么访问搬瓦工官网呢? 消息来源:搬瓦工优惠网->搬瓦工镜像站b...

flyzy2005
11分钟前
0
0
SpringBoot自动配置

本篇介绍下,如何通过springboot的自动配置,将公司项目内的依赖jar,不需要扫描路径,依赖jar的情况下,就能将jar内配置了@configuration注解的类,创建到IOC里面 介绍下开发环境 JDK版本1.8 spr...

贺小五
今天
3
0
命令行新建Maven多项目

参考地址 # DgroupId 可以理解为包名# DartifactId 可以理解为项目名mvn archetype:generate -DgroupId=cn.modfun -DartifactId=scaffold -DarchetypeArtifactId=maven-archetype-quickst......

阿白
今天
1
0
OSChina 周四乱弹 —— 上帝对我单身年限的惩罚越来越长了

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享张卫健的单曲《身体健康》 《身体健康》- 张卫健 手机党少年们想听歌,请使劲儿戳(这里) 昨天是重阳节咯, 可惜小小编辑总是晚...

小小编辑
今天
12
1
django rest framework 外键序列化方法与问题总结

django rest framework 外键序列化方法与问题总结 当借口中需要出现一对多关系的时候,我们可以用rest_framwork的序列化功能来处理,代码如下. # models.pyfrom django.db import modelscl...

_Change_
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部