PPP驱动程序的基本原理_第1页
PPP驱动程序的基本原理_第2页
PPP驱动程序的基本原理_第3页
PPP驱动程序的基本原理_第4页
PPP驱动程序的基本原理_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、ppp驱动程序的基木原理1) ppp设备是指在点对点的物理链路之间使用ppp帧进行分组交换的内核网络接口设备,由 于linux内核将串行设备作为终端设备來驱动,于是引入ppp终端规程來实现终端设备与 ppp设备的接口.根据终端设备的物理传输特性的不同,ppp规程分为异步规程(n_ppp)和同 步规程(n_sync_ppp)两种,对于普通串口设备使用异步ppp规程.2) 在ppp驱动程序中,每一 tty终端设备对应于一条ppp传输通道(chanell),每一 ppp网络 设备対应于一个ppp接口单元(unit).从终端设备上接收到的数据流通过ppp传输通道解码 后转换成ppp帧传递到ppp网络接

2、口单元,ppp接口单元再将ppp帧转换为ppp设备的接 收帧.反z,当ppp设备发射数据帧时,发射帧通过ppp接口单元转换成ppp帧传递给ppp 通道,ppp通道负责将ppp帧编码后写入终端设备.在配置了多链路ppp时 (config_ppp_multilink),多个ppp传输通道可连接到同一 ppp接口单元.ppp接口单元 将ppp帧分割成若干个片段传递给不同的ppp传输通道,反乙ppp传输通道接收到的ppp 帧片段被ppp接口单元重组成完整的ppp帧.3) 在linux-2.4屮,应用程序可通过字符设备/dev/ppp监控内核ppp驱动程序.用户可以用 ioctl(pppiocattac

3、h)将文件绑定到ppp接口单元上,来读写ppp接口单元的输出帧,也可 以用ioctl(pppiocattchan)将文件绑定到ppp传输通道上,来读写ppp传输通道的输入帧.4) ppp传输通道用channel结构描述,系统屮所有打开的传输通道在all_channels链表屮.ppp 接口单元用ppp结构描述,系统中所有建立的接口单元在all_ppp_units链表中.当终端设备 的物理链路连接成功后,用户使用ioctl(tiocsetd)将终端切换到ppp规程.ppp规程初始化 时,将建立终端设备的传输通道和通道驱动结构.对于界步ppp规程來说,通道驱动结构为 asyncppp,它包含通道操

4、作表async_ops.传输通道和接口单元各自包含自己的设备文件 (/dev/ppp)参数结构(ppp.file).;drivers/char/tty_io.c: int tty_register_ldisc(int disc, struct ttyjdisc *new_ldisc) if (disc < n_tty | disc >= nr_ldiscs)return -einval;if (newjdisc) ldiscsfdiscl = *newdisc;ldiscsdisc.flags |= ldisc_flag_defined; ldiscsdisc.num = disc

5、; elsememset(&ldiscsdisc, 0, sizeof(struct ttyjdisc);return 0;int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)struct tty_struct *tty, *real_tty;int retval;tty = (struct tty_struct *)file->private_data;if (tty_paranoia_check(tty, inode->i_rdev, nt

6、ty_ioctlu) return -einval;real_tty = tty;if(tty->driver.type = tty_driver_type_pty && tty->driver.subtype = pty_type_master) real_tty = tty->link;switch (cmd) case tiocgetd:return put_user(tty->ldisc.num, (int *) arg);case tiocsetd:return tiocsetd(tty, (int *) arg); if (tty->d

7、rive匚ioctl) int retval = (tty->driver.ioctl)(tty, file, cmd, arg);if (retval != -enoioctlcmd)return retval;if (tty->ldisc.ioctl) int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);讦(retval != -enoioctlcmd)return retval;return -einval;static int tiocsetd(struct tty_struct *tty, int *arg) i

8、nt retval, ldisc;retval = get_user(ldisc, arg);if (retval)return retval;return tty_setdisc(my, ldisc);/* set the discipline of a tty line. */static int tty_set_ldisc(struct tty_struct *tty, int ldisc)int retval = 0;struct ttydisc o_ldisc;char buf64;if (ldisc < n_tty) | (ldisc >= nr.ldiscs)retu

9、rn -einval;/* eduardo blanco */* cyrus durgin */if(!(ldiscslldiscj.flags & ldisc_flag_def1ned) 如果设定的规程不存在 char modname 20;sprintf(modname, htty-ldisc-%dm, ldisc);request_module (modname);尝试加载模块if(!(ldiscsldisc.flags & ldisc_flag_defined)return -einval;if (tty->ldisc.num = ldisc)return 0;

10、/* we are already in the desired discipline */ ojdisc = tty->ldisc;tty_wait_until_sent(tty, 0);等待终端输出设备的数据发送完/* shutdown the current discipline. */讦(tty->ldisc.close)(tty->ldisc.close)(tty);关闭原来的规程/* now set up the new line discipline */tty->ldisc = ldiscsidisc;tty->termios->c_line

11、 = ldisc;if (tty->ldisc.open)retval = (tty->ldisc.open)(tty);打开新规程if (retval <0) 如果打开失败,恢sz原来的规程tty->ldisc = o_ldisc;tty->termios->c_line = tty->ldisc.num;if (tty->ldisc.open && (tty->ldisc.open(tty) < 0) tty->ldisc = ldiscsn_tty;tty->termios->c_line =

12、n_tty;if (tty->ldisc.open) int r = tty->ldisc.open(tty);讦(r < 0)panic(mcouldn't open n_tty ldisc for " "%s error %d.", tty_name(tty, buf), r);if (tty->ldisc.num != ojdisc.num && tty->driver.set_idisc) tty->driver.set_ldisc(tty);return retval;drivers/char/

13、tty_ioctl.c:/* intemal flag options for termios setting behavior*/#define termios_flush 1#define termios.wait 2#define termios.termio 4void tty_wait_until_sent(struct tty_struct * tty, long timeout) declare_waitqueue(wait, current);#ifdef tty_debug_wait_until_sentchar buff64;printk("%s wait unt

14、il sent.n' tty_name(tty, buf);#endifif (! tty->drive ichars_in_bu ftcr)return;add_wait_queue(&tty->write_wait, &wait);if (!timeout)timeout = max_schedule_timeout;do #ifdef tty_debug_wait_until_sent printk("waiting %s.(%d)nh, tty_name(tty, buf), tty->drive r.chars_in_buffer(

15、tty);#endifset_current_state(task_interruptible);if (signal_pending(current)goto stop_waiting;讦(!tty->drive 匚 chars_in_buffer(tty)break;timeout = schedule_timeout(timeout); while (timeout);if (tty->drive 匚 wait_until_sent)tty->drive匚wait_until_sent(tty, timeout);stop_waiting:current->sta

16、te = task_running;remove_wait_queue(&tty>write_wait$ &wait);drivers/net/ppp_async.c:/* the basic ppp frame.*/#define ppp_hdrlen 4 /* octets for standard ppp header */#define ppp_fcslen 2 产 octets for fcs */#define ppp_mru 1500 /* default mru = max length of info field */#define obufsize 2

17、56/* structure for storing local state. */struct asyncppp 界步ppp通道的驱动结构struct tty_struct *tty;unsigned int flags;unsigned int state;unsigned int rbits;int mru;spinlock_t xmitjock;spinlock_t recvjock;unsigned long xmit_flags;u32 xaccm8;终端字符转换位图u32 raccm;unsigned int bytes_sent;unsigned int bytes_rcvd;

18、struct sk_buff *tpkt;int tpkt_pos;ul6 tfcs;unsigned char *optr;unsigned char *olim;unsigned long last_xmit;struct sk_buff called when a tty is put into ppp line discipline.*/static intppp_asynctty_open(struct tty_struct *tty)打开异步 ppp 规程rpkt; int lcp_fcs;struct ppp.channel chan; /* interface to gener

19、ic ppp layer */ unsigned char obufobufsizej;;static struct tty_ldisc ppp.ldisc = 界步 ppp 规程操作表 magic: tty_ld1sc_magic,name: mpppfopen: ppp_asynctty_open,close: ppp_asynctty_close,read: ppp_asynctty_read,write: ppp_asynctty_write,ioctl: ppp_asynctty_ioctl,poll: ppp_asynctty_poll,receive_room: ppp_asyn

20、ctty_room,receive_buf: ppp_asynctty_receive, write_wakeup: ppp_asynctty_wakeup,;struct ppp_channel_ops async_ops = ppp 通道驱动操作表 ppp_async_send,发送ppp帧到终端设备 ppp_as ynjioctl;intppp.async_init(void)模块初始化int err;err = tty_register_ldisc(n_ppp, &ppp_ldisc);注册 n_ppp 规程讦(err != 0)printk(kern_err 'ppp

21、_asy nc: error %d registering line disc an'1, err);return err;struct asyncppp *ap; int err;modn c_use_count;err = -enomem;ap = kmalloc(sizeof(*ap), gfp_kernel);if (ap = 0)goto out;/* initialize the asyncppp structure */memset(ap, 0, sizeof(*ap);ap->tty = tty;在驱动结构上设置打开终端指针ap->mru = ppp_mru

22、;spin_lock _init(&ap->xmit _lo ck);spin_lock_init(&ap>recvo ck);ap->xaccmf01 =ou;ap->xaccm3 = 0x60000000u;ap->raccm =ou;ap->optr = ap->obuf;ap->olim = ap->obuf;ap->lcp_fcs = -1;ap->chan.private = ap;在一般的ppp驱动结构上设置界步驱动结构指针 ap->chan.ops = &async_ops;界步通道

23、操作表ap->chan.mtu = ppp_mru;err = ppp_register_channel(&ap->chan);建立通道驱动程序的传输通道结构 讦(err)goto out_free;tty->disc_data = ap;在打开终端结构上设置驱动结构指针return 0;out_free:kfree(ap);out:mod_dec_use_count;return err;/* called when the tty is put into another line discipline* or it hangs up.* we assume tha

24、t while we are in this routine, the tty layer* wont call any of the other line discipline entries for the* same tty.*/static voidppp_asynctty_close(struct tty_struct *tty)struct asyncppp *ap = tty->disc_data;if (ap = 0)return;tty->disc_data = 0;ppp_unregister_channel(&ap>chan);if (ap-&g

25、t;rpkt != 0)kfree_skb(ap->rpkt);if (ap->tpkt != 0)kfree_skb(ap->tpkt);kfree(ap);mod_dec_use_count;严* read does nothing no data is ever available this way* pppd reads and writes packets via /dev/ppp instead*/static ssize_tppp_asynctty_read(struct tty_struct *tty, struct file *file, unsigned

26、char *buf, size_t count)return eagain;1/* write on the tty does nothing, the packets all come in* from the ppp generic stuff.*/static ssize_tppp_asynctty_write(struct tty_struct *tty, struct file *file, const unsigned char *buf, size_t count)return eagain;1static intppp_asynctty_ioctl(struct tty_str

27、uct *tty, struct file * file, unsigned int cmd, unsigned long arg)struct asyncppp *ap = tty->disc_data;int err, val;err = -efault;switch (cmd) case ppp10cgchan:取通道号err = -enxio;if (ap = 0)break;err = efault;if (put_user(ppp_channel_index(&ap->chan), (int *) arg) break;err = 0;break;case pp

28、piocgunit:取接口 单元号err = -enxio;if (ap = 0)break;err = -efault;if (put_user(ppp_unit_number(&ap->chan),(int *) arg) break;err = 0;break;case tcgets:case tcgeta:err = n_tty_ioctl(tty, file, cmd, arg);break;case tcflsh:/* flush our buffers and the serial port's buffer */ if (arg = tcioflush |

29、 arg = tcoflush) ppp_async_fl ush_output(ap);err = n_tty_ioctl(tty, file, cmd, arg);break;case fionread:val = 0;if (put_user(val, (int *) arg)break;err = 0;break;case pppiocattach:将传输通道连接到接口单元case pppiocdetach:将传输通道与接口单元脱离err = ppp_channel_ioctl(&ap->chan, cmd, arg);break;default:err = -enoio

30、ctlcmd;return err;/* flush output from our internal buffers.* called for the tcflsh ioctl.犁static voidppp_async_flush_output(struct asyncppp *ap)int done = 0;spin_lock_bh(&ap->xmit_lo ck);ap->optr = ap->olim;if (ap->tpkt != null) kfree_skb(ap->tpkt);ap->tpkt = 0;clear_bit(xm!t_

31、full, &ap->xmit_flags);done = 1;spin_unlock_bh (&ap->xmit_lock);if (done)ppp_output_wakeup(&ap->chan);/* no kernel lock - fine */static unsigned intppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table 水wait) retiim 0;static intppp_asynctty_room(struct tty_stru

32、ct *tty) return 65535;drivers/net/ppp_generic.c:* private data structure for each channel.* this includes the data structure used for multilink.*/struct channel 传输通道结构struct ppp.file file; /* stuff for read/write/poll */struct ppp_channel * chan; /* public channel data structure */ spinlock_t downl;

33、 /* protects 'chan; file.xq dequeue */ struct ppp *ppp; /* ppp unit wete connected to */ struct list_head clist; /* link in list of channels per unit */ rwlock_t upl; /* protects、ppp and "ulist* */#ifdef config_ppp_multilinku8 avail; /* flag used in multilink stuff */u8 had_frag; /* >= 1

34、 fragments have been sent */ u32 lastseq; /* mp: last sequence # received */ #endif /* config_ppp_multilink */;struct ppp_chiinnel 传输通道的通用驱动结构void private; /* channel private data */struct ppp_channel_ops *ops; /* operations for this channel */ int mtu; /* max transmit packet size */int hdrlen; /* a

35、mount of headroom channel needs */void *ppp; /* opaque to channel */* the following are not used at present */int speed; /* transfer rate (bytes/second) */ int latency; /* overhead time in milliseconds */ ;struct ppp_channel_ops 驱动操作表/* send a packet (or multilink fragment) on this channel.returns 1

36、 if it was accepted, 0 if not. */int (*start_xmit)(struct ppp_channel 凭 struct sk_buff *);/* handle an ioctl call that has come in via /dev/ppp */ int (*ioctl)(struct pppchannel unsigned int, unsigned long);/* data structure describing one ppp unit.* a ppp unit corresponds to a ppp network interface

37、 device* and represents a multilink bundle.* it can have 0 or more ppp channels connected to it.*/struct ppp struct ppp.file file; /an instance of /dev/ppp can be associated with either a ppp* interface unit or a ppp channel. in both cases, file->private_data* points to one of these*/struct ppp.f

38、ile 监控文件结构参数enum interface=1, channel kind;struct sk_bufflhead xq; /* pppd transmit queue */struct sk_buflhead rq; /* receive queue for pppd */ stuff for read/write/poll */struct list_head channels; /* list of attached channels */ int n_channels; /* how many channels are attached */ spinlock_t rlock

39、; /* lock for receive side */ spinlock_t wlock; /* lock for transmit side */ int mru; /* max receive unit */ unsigned int flags; /* control bits */ unsigned int xstate; /* transmit state bits */ unsigned int rstate; /* receive state bits */ int debug; /* debug flags */struct slcompress *vj; /* state

40、 for vj header compression */enum npmode npmodenum_npj; /* what to do with each net proto */ struct sk_buff *xmit_pending; /* a packet ready to go out */ struct compressor *xcomp; /* transmit packet compressor */ void *xc_state; /* its internal state */struct compressor *rcomp; /* receive decompress

41、or */void *rc_state; /* its internal state */ unsigned long last_xmit; /* jiffies when last pkt sent */ unsigned long last_recv; /* jiffies when last pkt rcvd */ struct net_device *dev; /* network interface device */ #ifdef config_ppp_multilink int nxchan; /* next channel to send something on */ u32

42、 nxseq; /* next sequence number to send */ int mrru; /* mp: max reconst, receive unit */ u32 nextseq; /* mp: seq no of next packet */ u32 minseq; /* mp: min of most recent seqnos */ struct sk_bufflhead mrq; /* mp: receive reconstruction queue */ #endif/* config_ppp_muutilink */ struct net_device_sta

43、ts stats; /* statistics */;wait_queue_head_t rwait; /* for poll on reading /dev/ppp */ atomic_t refcnt; /* # refs (incl /dev/ppp attached) */ int hdrlen; /* space to leave for headers */ struct iist_head list; /* link in all_* list */ int index; /* interface unit / channel number */;严* all_ppp_lock

44、protects the all_ppp_units* it also ensures that finding a ppp unit in the all_ppp_units list* and updating its file.refcnt field is atomic.*/static spinlock_t all_ppp_lock = spin_lock_unlocked; static list_head(all_ppp_units);/* all_channels_lock protects all_channels and last_channel_index,* and t

45、he atomicity of find a channel and updating its file.refcnt* field.*/static spinlock_t all_channels_lock = spin_lock_unlocked; static list_head(all_channeis);static int last_channel_index;/* create a new, unattached ppp channel.*/intppp_register_channel(struct ppp.channel *chan)struct channel *pch;p

46、ch = kmalloc(sizeof(struct channel), gfp_atomic);if (pch = 0)return -enomem;memset(pch, (), sizeof(struct channel); pch->ppp = null;pch->chan = chan; chan->ppp = pch; init_ppp_file(&pch->file, channel); pch->file.hdrlen = chan->hdrlen;#ifdef config_ppp_multilinkpch->lastseq

47、= -1;#end讦/* config ppp muutilink */spinocknit(&pch->downl);pch->upl = rw_lock_unlocked;spino ck_bh (&all_channels_lock); pch->file.index = +last_cha nn el_index; list_add(&pch>file.list, &all_channels); spin_unlock_bh (&all_channels_lock); mod_inc_use_count;return 0;

48、严* initialize a ppp_file structure*/static voidinit_ppp_file(struct ppp.file *pf, int kind)pf->kind = kind;skb_queue_headnit(&pf->xq);skb_queue_head _init(&pf->rq);atomic_set( &pf->refcntt 1);init_waitqueue_head(&pf->rwait);voidint ppp.channel_ioctl(struct ppp.channel

49、*chan, unsigned int cmd, unsigned long arg)struct channel *pch = chan->ppp;int err = -enotty;int unit;if (!capable(cap_net_admin)return -eperm;讦(pch = 0)return -einval;switch (cmd) case pppiocattach:讦(get_user(unit, (int *) arg)break;err = ppp_connect_channel(pch, unit);break;case pppiocdetach:er

50、r = ppp_disconnect_channel(pch);break;return err;/* connect a ppp channel to a ppp interface unit.*/static intppp_connect_channel(struct channel *pch, int unit)struct ppp *ppp;int ret = -enxio;int hdrlen;spinock(&all_pppo ck);ppp = ppp_fi nd_unit(unit);if (ppp = 0)goto out;write_lock_bh(&pch->upl);ret = -einval;if (pch->ppp != 0)goto outw;pppock(ppp);spin_lock_bh(&pch->downl);if (pch->chan = 0) /* need to check this? */ goto outr;if (pch->file.hdrlen > ppp->file.hdrlen) ppp-

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论