根据医学和我的体验、观察,一个人真正睡着觉最多只有两个钟头,其余都是浪费时间,躺在枕头上做梦,没有哪个人不做梦。至于醒来觉得自己没有做梦,那是因为他忘记了。
通常一个人睡两个钟头就够了,为什么有人要睡七、八个钟头?那是你赖床躺在枕头上休息的习惯养成的,并非我们需要那么久的睡眠时间,尤其打坐做功夫的人 晓得,正午只要闭眼真正睡着三分钟,等于睡两个钟头,不过要对好正午的时间。夜晚则要在正子时睡着,五分钟等于六个钟头。
就这个时间的学问又大了,同宇宙法则、地球法则、易经阴阳的道理有关系,而且你会感觉到,心脏下面硬是有一股力量降下来,与丹田(肾上)的力量融合,所谓"水火既济",豁然一下,那你睡眠够了,精神百倍。
所以失眠或真要夜里熬夜的人,正子时的时刻,哪怕二十分钟也一定要睡,睡不着也要训练自己睡着。
过了正子时大约十二点半以后,你不会想睡了,这很糟糕。更严重的,到了天快亮,四、五点钟,五、六点卯时的时候,你又困得想睡,这时如果一睡,一天都会昏头。
所以想从事熬夜工作的人,正子时,即使有天大的事也要摆下来,睡它半小时,到了卯时想睡觉千万不要睡,那一天精神就够了。
不过失眠的人都挨过十二点,在床上翻来覆去睡不着,结果快天亮睡着了,到第二天下午都昏头昏脑,因此你会感觉失眠、睡眠不足,实际上是你没有经验。
(没想到睡眠也有这么高深的学问,我试了一下,果真如此。只在子时小睡了半小时,就起来一直到四点钟才睡,居然,六点钟就自己醒了!要是在平时,我一般是要睡到九、十点钟以后才能起来的。大家也可试试,觉得有效果就顶一下吧。)
睡眠与养生
一、睡眠的规则
战国时名医文挚对齐威王说:"我的养生之道把睡眠放在头等位置,人和动物只有睡眠才生长,睡眠帮助脾胃消化食物,所以,所以睡眠是养生的第一大补,人一个晚上不睡觉,其损失一百天也难以恢复。"
晚21点到凌晨5点为有效睡眠时间。人是动物,和植物同属于生物,白天(凌晨5点到晚上21点)活动产生能量,晚上(21点到凌晨5点)开始进行细胞分 裂,把能量转化为新生的细胞,是人体细胞休养生息、推陈出新的时间,也是人随着地球旋转到背向太阳的一面。阴主静,是人睡眠的良辰,此时休息,才会有良好 的身体和精神状态。这和睡觉多的婴儿长得胖、长得快,而爱闹觉的孩子发育不良是一样的道理。
睡觉是养生的一大功能,养就是用大量的健康细 胞去取代腐败的细胞,如一夜睡不着就换不了新细胞。如果说白天消亡一百万个细胞,一晚上只补回来五十万个细胞,这时你的身体就会出现亏空,时间长了,人就 糠了,像糠萝卜似的。为什么世上有百岁老人呢?因为他们每晚都在21点钟准时睡觉。
植物吸收阳光的能量,夜里生长,所以夜晚在农村的庄稼 地里可听到拔节的声音。人类和植物同属于生物,细胞分裂的时间段大致相同,错过夜里睡觉的良辰,细胞的新生远赶不上消亡,人就会过早的衰老或患病,人要顺 其自然,就应跟着太阳走,即天醒我醒,天睡我睡。人在太阳面前小如微尘,"与太阳对着干"是愚蠢的选择,迟早会被太阳巨大的引力催垮。这是客观真理。
现实生活中,不少人有入睡难,睡眠质量不高的毛病。睡眠不好是一个综合性的问题,如肝火过盛,睡觉警觉;胃火过剩,睡觉不安;肝阴不足,睡觉劳累。
二、睡眠与疾病
现代的生活习惯和生活方式给人们的身体带来了很多负面影响形成"四大病":水果病、冰箱病、电视电脑病、熬夜病。肝脏有一特点:卧则回血,坐立向外供血。
子时(23:00―1:00),其实23点就是新的一天的开始,并不是0点开始的,这是我们犯的误识。肝胆相表里,互为一家,23点胆经开了,如若不 睡,大伤胆气,由于十一脏腑皆取决于胆也,胆气一虚,全身脏腑功能下降,代谢力、免疫力纷纷下降,人体机能大大降低,胆气支持中枢神经,胆气受伤易患各种 精神疾病,比如抑郁症、精神分裂症、强迫症、躁动症等。子时胆要更换胆汁,胆经渐旺人如不卧,胆汁更替不利,过浓而结晶成石,久之即得胆结石,如果把胆给 摘了,一摘就胆怯了,全身的免疫力下降了50%以上,所以不能摘,要用它本系统的巨大潜能把它化掉。
丑时肝经最旺,丑时(1:00― 3:00)不眠,肝无法解除掉有毒之物,产生新鲜血液,因藏血不利,面呈青色,久之易患各类肝病,现在有些人肝不太好,特别在欧洲平均4个人就有一个大三 阳或是小三阳,大都是因为违反自然规律过了子时不睡觉造成的。甲肝比较好治,乙肝就很难治。乙肝病毒携带者,是由于晚上经常不睡觉,人太虚弱了,也就是说 秩序太乱了,病毒已经到了细胞里了。也就是说乙肝的病毒已经到了细胞里面,但是现在它还没有能力造成肝炎,当人身体处于最薄弱的时候就形成成肝炎,乙型肝 炎就意味着将来40%――60%的肝硬化。聪明的人是应该了解天、地、人之间的关系,不聪明的人就是应该被淘汰的人。
肝主疏泄,过子时不睡,可引起肝疏泄不利,肝气郁结,可见易怒,头痛头晕,眼红,眼痛,耳鸣,耳聋,胸肋胀痛,女性月经不调,便秘,也可引起肝气升发不足,人会目倦神疲,腰膝酸软,晕眩,失眠,惊悸,精神恍惚,重则会晕倒在大街上,不省人事。
肝有藏血、调节血液的功能,过子时不睡,会造成肝血不足,还会引起吐血、流鼻血、皮下出血、牙龈出血、眼底出血、耳出血等出血证状。
肝开窍于目,过子时不睡,易引起肝虚,则出现视力模糊、老花、夜盲、畏光、迎风流泪,等症状,还会形成青光眼、白内障、眼底动脉硬化、视网膜病变等眼疾。
肝主筋,其华在爪,过子时不睡觉,会引起肝血不足,就出现筋痛,麻木,屈伸困难,痉挛抽搐,易造成灰指甲,缺钙,髌骨软化,癫痫病,骨质疏松等症。
肝与心,过子时不睡觉,可引起肝血不足,由于心主一身之血脉,肝有储藏和调节血液的功能,会造成心脏供血不足,引起心慌、心颤等症状,严重的形成心脏病、高血压等心脑血管疾病。
肝与脾,过子时不睡觉,会引起肝胃不和,由于肝助脾胃消化,由于肝气太虚不能助脾胃消化,使人脾胃消化功能不好,表现为舌苔厚,长期以来会造成中气塌陷。
肝与肺,过子时不睡觉,无法滋阴潜阳,肝阴亏损,引起肝火过盛灼肺,出现干咳、或咳嗽、咳痰血等木火刑金的证状,易导致牛皮癣等各种皮肤病。
肝与肾,过子时不睡觉,肝虚导致肾亏,由于肝肾同源,容易造成生殖系统疾病、不育、骨病、牙病、脱发、糖尿病、肾衰竭等疾病。
三、睡眠的方法
交通规则――你不懂就容易出事故。比如说,23点至凌晨3点为子丑时,胆肝经最活跃的时候,肝胆要回血,"躺下去回血,站起来供血"。如果你每晚22点 钟左右躺下,静静得不要说话,到23点的时候,也就睡着了。肝胆开始回血,把有毒的血过滤掉,产生新鲜的血液,到一百岁也没有胆结石,也没有肝炎、囊肿一 类的病。如果你天天熬夜到1点多,肝回不了血,有毒的血排不掉,新鲜的血生不成,胆又无法换胆汁,所以这些人容易得胆结石、囊肿、大三阳、小三阳各种病 症。
在欧洲地区,平均四个人就有一个肝炎病毒携带者,这就叫不懂规则。睡前半小时最好不要讲话,睡觉的时候更不要说话,如一说话,肺经动,然后心经又动,(因为心肺共为上焦)人就容易进入兴奋状态,所以就很难入睡。
21:00―23:00为亥时。亥时三焦经旺,三焦通百脉。亥时入眠,百脉皆得濡养,故百岁老人得共同特点即21:00(亥时)之前入睡。女性若想长久的保持容颜娇好,应做到早睡早期。
睡觉要关窗,不能开风扇、不能开空调,人生病很多都与此有关,因为人在睡眠之中,气血流通缓慢,体温下降,人体会在表面形成一种阳气层,这种阳气层它使 人叫"鬼魅不侵",什么意思呢,阳气足的人,不做恶梦,就是这种阳气,占了上风。开空调,开风扇,情况就不一样了,开窗户,窗户走的是风,风入的是筋,如 果开空调,也有风,风入筋,寒入骨,早上起来,身上发黄,脸发黄,脖子后面那条筋发硬,骨节酸痛,甚至有人就开始发烧,这就是风和寒侵入到了筋和骨头里的 缘故,这也就是气受伤了。如果说晚上睡觉不开窗,不开空调,不开风扇,连房门也关上,效果最好,如果热,把房门打开,把窗户关上,效果就差了一点,但是他 不至于第二天早上起来浑身乏力,后背僵硬.
有人把客厅的空调开开了,把卧室的门打开,和直接开空调睡觉是差不多的,开了空调以后,空调那个寒进了骨了,所以心里发冷,心在哪,心在脑髓,脑为髓之海,骨髓里有寒,那肯定心里就寒了,怎么办,补肾阳、补中气,什么时候补到心里不冷,烧就退了,寒走出去了。
睡觉要尽量早睡,睡得晚,伤了少阳之气,必然第二天是疲倦无力,要关上窗户,不开空调、电扇,保护阳气。
肝胆在下焦,如果胃出现问题的时候,他就会出现寝睡不安,一个是胃寒,如果这个人胃阳本来就不足,过多的喝绿茶,就会出现胃寒,胃寒的时候人是睡不好觉的,或者吃带泥沙之物过多,胃隐隐作寒,肯定是睡不好;
再一个是胃热,就是热气往上走,嘴里喘的都是热气,像这种情况也睡不好觉;再一个是胃燥,口干舌燥,胃里感觉到燥;
还有一个就是胃厚,气味的味,胃厚,这种情况就是吃了这种厚腻的味道,有人吃海鲜、吃鱼、吃炖鸡,味道好鲜美,吃多了,美味不可多用,这些东西在里面要稀释它,不稀释它,它在里面味太厚了,所以这个也睡不好觉;
再一个腹涨,腹是涨鼓鼓的,也睡不着,翻来覆去也睡不着;再一个是胃气太虚,冒冷汗,这也睡不好觉,这些原因都可能形成胃不宁,胃不宁就睡不好。
睡觉时要肢暖,四肢要暖,因为四肢是阳之本,这个大家都知道了,四肢不暖,肯定是肾阳不足,应该在睡觉之前把手脚捂暖,手脚和肚脐、背后的命门都要盖好。
睡眠法因人而异,下面介绍3种做法:
1、睡觉前简单的压腿,然后在床上自然盘坐,两手重叠放于腿上,自然呼吸,感觉全身毛孔随呼吸一张一合,若能流泪打哈欠效果最佳,到了想睡觉时倒下便睡。
2、仰卧,自然呼吸,感觉呼吸像春风,先融化大脚趾,然后是其他脚趾,接着脚、小腿、大腿逐渐融化。如还未醒着,再从头做。
3、入睡快的人可右侧卧,右手掌托右耳。右掌心为火,耳为水,二者形成水火即济,在人体中形成心肾相交。久之,养心滋肾。
睡眠一定要早起,即使在冬天,也不可超过6点起床,春夏秋季尽量在5点之前起床,因为人在寅时(3点―5点)肺经旺的时候起床,能够使肺气得以舒展,以 顺应阳气的舒长,来完成新陈代谢,肃降浊气,使肺气清,这样有助于养肺和顺应太阳的天势升起人体阳气,使人一天阳气充足,否则,就好像发动机,过了这段好 时机就很难发动人体阳气,人体阳气淤积在人体下部不能由命门向上发动升起,会形成淫气,严重损害人的身心健康。
早晨5点至7点是人体大肠 经最旺的时候,人体需要把代谢的浊物排出体外,此时如果不起床,大肠得不到充分活动,无法很好的完成排浊功能,使浊物停留而形成毒素,危害人体血液和脏腑 百骸。早晨7点到9点人体胃经最旺,9点到11点人体脾经最旺,这时人的消化吸收运化的能力最好,如果这时还不起床,人体胃酸会严重腐蚀胃粘膜,人体在最 佳吸收营养时间得不到营养,长期以来会患脾胃疾病,造成营养不良、中气塌陷。所以千万不要赖床,赖床会造成头昏、疲惫不堪、睡眠不足的感觉,而应按时起 床,历史上许多伟人都是有三四点钟起床的习惯,比如华盛顿、拿破仑、康熙皇帝、曾国藩等。另外早起能增加工作效益,俗话说:"三天早起,一天工"。
现代医学证明,早睡早起的人精神压力较小,不易患精神类疾病。早晨不要太早出去锻炼,因为早晨在太阳没有出来之前,地下道的漳气、浊气正往上走(尤其是城市),这些气对人体损伤是很严重的。
养身三大事,一睡眠,二便利,三饮食,其余起居、服装等皆是辅助。
三事中睡眠第一。然胃纳不和者,夜眠不安,故以通便利为第二。而饮食无节,饥饱过度者,肠胃必受伤,而营养日减。睡以安神为主,神以心安为主,应配合年 龄,壮年至多七小时至八小时,多睡则智昏头晕眼红胀,四肢疲软,童年必睡足八小时,或过九小时勿碍,老或病人至多六小时已足。
应注意:
(一)睡眠宜早,勿过十时,老年人以八点为正,勿过九点。凡交十一时,为阳生时,属肾,此时失眠,肾水必亏,心肾相连,水亏则火旺,最易伤神。千万勿以安眠药片助睡。
(二)枕上切忌思索计算未来事,睡时宜一切不思,鼻息调匀,自己静听其气,由粗而细,由细而微细而息。视此身如无物,或如糖入于水,化为乌有,自然睡着。
(三)如有思想,不能安着,切勿在枕上转侧思虑,此最耗神,可坐起一时再睡。
(四)如在午时,即上午十一点至一点,为阴生之时,属心,此时如不能睡,可静坐一刻钟,闭目养神,则心气强。凡有心脏病者切宜注意,每日于此二时注意,则元气日强,无心跳腹泄或小便频速之病。
(五)夏日起宜早,冬日起宜迟。居北方宜防寒气,如在粤桂等省,早起防山岚瘴气中病。食后勿仰天睡,早起如在寅时三点至五点,此时切忌郁怒,必损肺伤肝,万望注意。
【子时】夜半,又名子夜、中夜:十二时辰的第一个时辰。(北京时间23时至01时)。
【丑时】鸡鸣,又名荒鸡:十二时辰的第二个时辰。(北京时间01时至03时)。
【寅时】平旦,又称黎明、早晨、日旦等:时是夜与日的交替之际。(北京时间03时至05时)。
【卯时】日出,又名日始、破晓、旭日等:指太阳刚刚露脸,冉冉初升的那段时间。(北京时间05时至07时)。
【辰时】食时,又名早食等:古人"朝食"之时也就是吃早饭时间,(北京时间07时至09时)。
【巳时】隅中,又名日禺等:临近中午的时候称为隅中。(北京时间09 时至11时)。
【午时】日中,又名日正、中午等:(北京时间11时至13时)。
【未时】日�,又名日跌、日央等:太阳偏西为日跌。(北京时间13时至15时)。
【申时】哺时,又名日铺、夕食等:(北京时间15食至17时)。
【酉时】日入,又名日落、日沉、傍晚:意为太阳落山的时候。(北京时间17是至19时)。
【戌时】黄昏,又名日夕、日暮、日晚等:此时太阳已经落山,天将黑未黑。天地昏黄,万物朦胧,故称黄昏。(北京时间19时至21时)。
【亥时】人定,又名定昏等:此时夜色已深,人们也已经停止活动,安歇睡眠了。人定也就是人静。(北京时间21时至23时)。
2009年2月25日星期三
一个睡五分钟等于六个钟头的方法
2009年2月24日星期二
Linux 中IP包过滤的实现
一、 Linux网络部分代码分析
Linux 网络层采用统一的缓冲区结构skbuff,一个个单独的skbuff被组织成双向链表的形式。网卡接收到数据帧后,系统内核为接收到的数据帧分配一块内 存,然后将数据整理成skbuff的结构.在网络协议处理的时候,数据均以skbuff的形式在各层之间传递、处理。
skbuff的强大功能在于它提供了众多指针,可以快速的定位协议头位置;它也同时保留了许多数据包信息(如使用的网络设备等),以便协议层根据需要灵活应用.
整个网络层的流程如下(以两个进程通过TCP/IP进行通信为例):
在IP协议层有三个关键函数:ip_rcv( )、ip_forward( )、ip_output( ),分别处理IP层的接收、转发和发送工作。防火墙的功能函数将在此三个函数中调用。
二、 包过滤.
包 过滤主要工作于IP层。Linux在应用层利用ipchains( )来实现对包过滤的实现。可以用该函数实现过滤规则的添加、删除、设置、更改,在对包过滤规则进行设置的同时,还可以指定对数据包进行IP伪装。在 Linux 内核中有三条内置的规则链(input chain, forward chain, output chain),分别对应接收检测,转发检测和发送检测(内置链不可删除),每一条chain 包含一系列过滤规则及链的缺省策略.利用各规则链可以对输入、转发、和输出的数据包进行过滤。
其实现过程如下:
*在不同检测点进入相应过滤链.
*顺序检查每一条过滤规则,找出与之匹配的规则(ACCEPT, REJECT, DENY, MASQ,REDICT,RETURN).
*当遇到第一条匹配的规则时采取以下行动:
a. 将规则应用于此数据包;
b. 每条规则都包含有packet和byte数的计数器,当匹配时,此计数器加
c. 如果设置记录功能,则记录.
*当没有规则匹配时,采用链的缺省策略.
具体流程结合代码来说:
三种内置规则链分别作用于对应的三个函数ip_rcv( )、ip_forward( )和ip_output( )。
1、ip_rcv()是IP层的接收函数,由它来处理网卡接收到的数据包,它首先检查:
a.长度是否正确;
b..版本号是否正确(是IPV4还是IPV6?);
c.校验和是否正确.
在确定这些信息无误后,则调用包过滤检测:
fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);
call_in_firewall 会对输入的数据包进行规则检查,fwres返回的便是匹配出来的规则.如果对应的规则为不接受该数据包,则立即将此数据包丢弃:
if (fwres <>daddr, iph->saddr, iph->tos, dev)
此时路由信息已包括在了skbuff数据结构的dst 项中,紧接着调用
skb->dst->input(skb) 继续处理 .
对发往本地高层协议的包,则调用ip_local_deliver(),进行处理。
对转往其他主机的包,则实际调用ip_forward()处理。
值 得注意的是,经伪装的包在回来时,其目的IP是防火墙的IP,经路由后,也送入ip_local_deliver( )处理,在ip_local_deliver( )内部先解伪装,然后再查一次路由,发往本地的直接送往高层,,否则依然调用ip_forward( )。
2、ip_forward( )用来处理发往其他主机的数据包,其函数流程为:
1)、因为ip_forward()接收的参数是一个skbuff,它首先利用skbuff的指针,把IP头找出:
iph = skb->nh.iph
2)、因为ip_forward()由ip_rcv()调用,而在ip_rcv()中已查过了路由,此处只需利用skbuff的指针定位路由信息即可:
struct rtable *rt; /* Route we use */
rt = (struct rtable*)skb->dst;
3)、如果此IP包的生存时间(ttl)已到,则丢弃.
if (iph->ttl <= 1) goto too_many_hops; 4)、如果在选项中指定了严格的源路由功能(strict source routing) ,且此处无法达到,也丢弃: if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
goto sr_failed;
5)、如果指定的伪装功能,且上层协议是ICMP,则在此处处理一部分,且跳过后面的包过滤处理
#ifdef CONFIG_IP_MASQUERADE
if(!(IPCB(skb)->flags&IPSKB_MASQUERADED)) {
if (iph->protocol == IPPROTO_ICMP) {
........
fw_res = ip_fw_masq_icmp(&skb, maddr);
if (fw_res)
/* ICMP matched - skip firewall */
goto skip_call_fw_firewall;
........
}
}
#endif
6)、如果上一步的前提不成立,则要经过一次包过滤.
fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
7)、在当前linux版本中,包过滤与伪装功能在许多地方是紧密联系在一起的,如采用同样的配置工具ipchains,同样的配置接口setsocketopt(),其中是否启动伪装的标志也在防火墙的chains中.
8)、因为伪装可能改变了skbuff的一些信息,此时要重新定位一下IP头及其选项:
iph = skb->nh.iph;
opt = &(IPCB(skb)->opt);
9)、因为转发的数据总是要送出的,紧接着会调用call_out_firewall(),并把数据送出去.
3、在ip_local_deliver()中.
1).如果需要,首先重组IP包:
if (sysctl_ip_always_defrag == 0 &&
(iph->frag_off & htons(IP_MF|IP_OFFSET))) {
skb = ip_defrag(skb);
if (!skb)
return 0;
iph = skb->nh.iph;
2).然后调用ip_fw_demasquerade解开IP伪装。
ret = ip_fw_demasquerade(&skb);
3)、再次调用路由查找,根据真正的IP来发送此包.
ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, skb->dev)
4).根据路由发往上层或是转发(略).
在对数据包进行处理的全部过程中,分别调用了以下三个函数:
call_in_firewall(), call_fw_firewall()和 call_out_firewall()。察看这三个函数的具体实现发现,其核心过程都在于ip_fw_check() 这个函数,它完成了数据包与规则的实际匹配.
ip_fw_check()函数分析:
防 火墙的规则链由ip_chain数据结构描述,其中包含了指向链中第一条规则的指针和链的缺省策略。规则链中的每条规则由ip_fwkernel数据结构描述。ip_fw_check()所做的就是将每一个ip包与规则链中的每一条规则(实际就是ip_fw数据结构所描述的内容)按照链表的组织顺序一一比较,若匹配则并返回规则的行动项。
结束语
以上简单的介绍了linux下实现包过滤的基本方法,希望对大家起到抛砖引玉的作用。
From: http://sje.cn/S_Html/38/12/31/7554.html
使用socket BPF
by Quickmouse(quickmouse@263.net)
第一次听说socket BPF的东西是CTO说sniffer要注意效率问题,需要针对规则设定一定的过滤规则,这样可以减少程序在用户空间和内核空间的切换。于是就去 google那个东西了。不过结果并不是很理想的,似乎研究这个的人不多。从方方面面的情况看,似乎用libpcap库设置BPF的过滤器是比较容易的, 但是我的机器并没有装libpcap,man了半天就是没有东西,呵呵。不过折腾了一下也是弄出来了,那都是大半年前的事情了。今天写程序又用到BPF 了,突然想到应用过程当中有一个逻辑问题,所以就想顺便写点什么吧。如果你不想装libpcap库,又想折腾BPF,看这篇文章就对了。不过,如果你是打 算空手套白狼,不会用tcpdump,或者想从头学怎么写BPF规则,那我还没有钻研得那么深,咱们可以以后讨论讨论,呵呵。
设置BPF过滤器是通过setsockopt调用来完成的,格式如下:
setsockopt(sd, SOL_SOCKET, SO_ATTACH_FILTER, &Filter, sizeof(Filter));
这个调用的格式大家都很熟悉了,不清楚的在参数Filter的设置上。Filter的定义是struct sock_fprog Filter; 此结构在linux/filter.h当中有定义:
struct sock_fprog /* Required for SO_ATTACH_FILTER. */
{
unsigned short len; /* Number of filter blocks */
struct sock_filter *filter;
};
其中的filter指针指向结构为struct sock_filter的BPF过滤代码。结构同样也在同一个文件当中定义:
struct sock_filter /* Filter block */
{
__u16 code; /* Actual filter code */
__u8 jt; /* Jump true */
__u8 jf; /* Jump false */
__u32 k; /* Generic multiuse field */
};
其实我们并不关心如何具体的编写struct sock_filter内的东西,因为tcpdump已经内置了这样的功能。例如,想要对所接受的数据包过滤,只想接收udp数据包,那么在 tcpdump当中的命令就是tcpdump udp。如果你想让tcpdump帮你编译这样的过滤器,则用tcpdump udp -d,可以得到输出:
[root@Kernel26 root]# tcpdump udp -d
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 4
(002) ldb [20]
(003) jeq #0x11 jt 7 jf 8
(004) jeq #0x800 jt 5 jf 8
(005) ldb [23]
(006) jeq #0x11 jt 7 jf 8
(007) ret #96
(008) ret #0
瞧,这就是BPF的代码了,看不懂吧@_@,其实挺像汇编的,琢磨一下就会了,ld开头的表示加载某地址数据,jeq是比较啦,jt就是jump when true,jf呢就是jump when false,后面表示行号。不过这样的东西用在程序里还是不习惯,再用tcpdump udp -dd,可以得到:
[root@Kernel26 root]# tcpdump udp -dd
{ 0x28, 0, 0, 0x
{ 0x15, 0, 2, 0x000086dd },
{ 0x30, 0, 0, 0x00000014 },
{ 0x15, 3, 4, 0x00000011 },
{ 0x15, 0, 3, 0x00000800 },
{ 0x30, 0, 0, 0x00000017 },
{ 0x15, 0, 1, 0x00000011 },
{ 0x6, 0, 0, 0x00000060 },
{ 0x6, 0, 0, 0x00000000 },
哈哈,这个像什么?像c当中的数组的定义吧。不错,这个就是过滤udp包的struct sock_filter的数组代码。把这部分复制到程序当中,将Filter.filter指向这个数组,Filter.len设置长度,就可以用 setsockopt设置过滤器了。
不过使用这样的过滤器还是有一些需要注意的问题的,例如,设置一个过滤器,只允许两个源MAC地址的数据包进入,我们先用:
[root@Kernel26 root]# tcpdump ether src 01:02:03:04:05:06 or ether src 04:05:06:07:08:09 -dd
{ 0x20, 0, 0, 0x00000008 },
{ 0x15, 0, 2, 0x03040506 },
{ 0x28, 0, 0, 0x00000006 },
{ 0x15, 3, 4, 0x00000102 },
{ 0x15, 0, 3, 0x06070809 },
{ 0x28, 0, 0, 0x00000006 },
{ 0x15, 0, 1, 0x00000405 },
{ 0x6, 0, 0, 0x00000060 },
{ 0x6, 0, 0, 0x00000000 },
生成模板,我们注意到第2、4行比较了第一个MAC地址,第5、7行比较了第二个MAC地址,所以我们只需要在我们的程序当中动态的改变这四行当中的数值就可以了,例如:
SetFilter(char *mac1, char *mac2)
{
struct sock_filter code[]={
{ 0x20, 0, 0, 0x00000008 },
{ 0x15, 0, 2, ntohl(*(unsigned int *)(mac1 + 2)) },
{ 0x28, 0, 0, 0x00000006 },
{ 0x15, 3, 4, ntohs(*(unsigned short *)mac1) },
{ 0x15, 0, 3, ntohl(*(unsigned int *)(mac2 + 2)) },
{ 0x28, 0, 0, 0x00000006 },
{ 0x15, 0, 1, ntohs(*(unsigned short *)mac2) },
{ 0x6, 0, 0, 0x00000060 },
{ 0x6, 0, 0, 0x00000000 }
};
...
}
这里,需要用ntohl/ntohs等函数将网络字节序转换为主机字节序。但是这段代码是有逻辑问题的。它首先比较第一个mac地址的后4个字节,如果不 正确转入比较第二个mac地址,如果正确转入比较第一个mac地址的高2个字节。因此,如果打算将这个代码用作通用的mac比较,那么在输入的两个mac 地址后4字节都相同的情况下就会出现逻辑覆盖错误,即无法对满足第二个mac地址的条件进行判断。因此在这种情况下必须要准备两段比较代码,根据情况进行 设置。具体不再累述。
此外,这段BPF代码还存在的一个问题是,一般情况下tcpdump只返回所捕获包的头96字节,也就是0x60字节,可见代码的倒数第二行是ret #96。对于需要完整的包处理还是不行的,因此你需要将其设置为0x0000ffff,或者在用tcpdump生成的时候用tcpdump -s 65535 -dd ... 来生成。
最后,用tcpdump生成的BPF代码只能用于SOCK_RAW的socket,这类socket是可以直接操作数据链路层的,如果你打算将BPF用于 ip层等较高层次的socket,那么你需要手工修改部分行的code.k,也就是修改如ldh [12]当中的[12]这个数值,因为这个数值的偏移量是按照从链路层开始计算得到的,在没有链路层之后,这个值就发生了变化,这个是需要注意的。
参考资料:《Linux下Sniffer程序的实现》作者:Gianluca Insolvibile,
http://www.nsfocus.net/index.php?act=magazine&do=view&mid=1797
From: http://blog.donews.com/quickmouse/archive/2004/11/17/173266.aspx
使用Ioctl向Linux内核传递参数的方法
一、应用层
uint16 data16;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket failednr");
}
if(ioctl(fd, SIOCSIFVLAN_PVID_PRI, &data16) < 0)
{
printf("ioctl pvid failednr");
}
二、linux内核
1、 在sockios.h中定义
#define SIOCSIFVLAN_PVID_PRI 0x8985 /* Set 802.1Q VLAN pvid */
2、在af_inet.c中添加:
extern int VLAN1QEN(unsigned int ,void *arg);
在inet_ioctl()函数中添加
case SIOCSIFVLAN_PVID_PRI:
return VLAN1QEN(cmd, arg);
3、另外定义:
static unsigned int VLAN_PVID_PRI = 0;
int VLAN1QEN(unsigned int cmd,void *arg)
{
unsigned int data;
if (copy_from_user(&data, arg, sizeof(int)))
return -EFAULT;
switch (cmd) {
case SIOCSIFVLAN_PVID_PRI:
VLAN_PVID_PRI = data;
break;
default:
return -EINVAL;
}
}
From: http://soft.zdnet.com.cn/software_zone/2007/1023/574178.shtml
2009年2月23日星期一
vxworks下怎么改mac地址
关于动态修改VXWORKS下MAC地址的问题!
由于我用的FREESCALE的COLDFIRE MCF527X系列的芯片,
如下图:
CPU: Motorola M5275AB. Processor #0.
Memory Size: 0x2008000. BSP version 1.2/0.
WDB Comm Type: WDB_COMM_END
WDB: Ready.
-> d 0xffffff00
ffffff00:
ffffff10: 3139 322e 3136 382e 302e 3135 3520 683d *192.168.0.155 h=*
ffffff20: 3139 322e 3136 382e 302e 3337 2067 3d31 *192.168.
ffffff30: 3932 2e31 3638 2e30 2e32 2075 3d74 7220 *92.168.0.2 u=tr *
ffffff40: 7077 3d31 2074 6e3d 7472
ffffff50: 6665 6331 00ff ffff ffff ffff ffff ffff *fec1............*
ffffff60: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffff70: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffff80: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffff90: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffa0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffb0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffc0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffd0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffe0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
fffffff0: ffff ffff ffff ffff
value = 21 = 0x15
系统启动的时候,自己会从这LOAD MAC地址!
用的是以下的函数:
/*****************************
*
* sysFecEnetAddrGet - return an ethernet address for the board
*
* RETURNS: OK
*
* NOMANUAL
*/
STATUS sysFecEnetAddrGet
(
UINT32 motCpmAddr,
UCHAR * enetAddr
)
{
#ifndef ETHERNET_ADR_SET
memcpy(enetAddr, motFecEnetAddr, 6);
return(OK);
#else
int index;
char enetAddrTemp[6];
STATUS return_status;
return_status = sysEnetAddrGet( 0, (UINT8 *)enetAddrTemp);
/* swap bytes */
for ( index = 0; index < 6; index++)
{
enetAddr[index] = enetAddrTemp[5 - index];
}
#endif
}
#endif /* INCLUDE_END */
其实关键的是这个函数:sysEnetAddrGet
/*****************************
*
* sysEnetAddrGet - get the hardware Ethernet address
*
* This routine determines the unique Ethernet address for the CPU board and
* copies it to
* high-order byte is `addr[5]'. The memory area pointed to by
* six bytes.
*
* RETURNS: OK, or ERROR if the Ethernet address cannot be returned.
*/
STATUS sysEnetAddrGet
(
int unit,
UINT8 * addr
)
{
char bytes[7];
if (unit != 0)
return (ERROR);
/* read the variable address bytes */
sysNvRamGet (bytes, 6, ENET_NVRAM_OFFSET);
/* if the network address is not initialized, return ERROR */
if ( (bytes[0] == -1) && (bytes[1] == -1)
&& (bytes[2] == -1) && (bytes[3] == -1)
&& (bytes[4] == -1) && (bytes[5] == -1))
{
return (ERROR);
}
addr[5] = ((ENET_DEFAULT & 0x0000ff00) >> 8); /* High order */
addr[4] = ((ENET_DEFAULT & 0x00ff0000) >> 16);
addr[3] = ((ENET_DEFAULT & 0xff000000) >> 24);
addr[2] = bytes[3];
addr[1] = bytes[4];
addr[0] = bytes[5]; /* Low order */
return (OK);
}
这是获取MAC地址的函数:sysNvRamGet
STATUS sysNvRamGet
(
char *string, /* where to copy non-volatile RAM */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into non-volatile RAM */
)
{
char *read_ptr;
if ((strLen < 0) || (offset < 0 )
|| ((offset + strLen) > NV_RAM_SIZE))
return (ERROR);
read_ptr = (char *)offset; /* boot line begins at
while (strLen--)
{
*string = NV_RAM_READ (read_ptr);
string++, read_ptr++;
}
*string = EOS;
return (OK);
}
但是怎么设呢???
******************************
*
* sysEnetAddrSet - set the Ethernet address for this board
*
* This routine sets the variable portion of the Ethernet address, the first
* three bytes contain a fixed manufacturer's code, while the last 3 bytes are
* set locally, to generate a unique Ethernet address on the local network.
*
* RETURN: OK, always.
*
* NOMANUAL
*/
STATUS sysEnetAddrSet
(
char byte5, /* Ethernet address high order byte */
char byte4,
char byte3,
char byte2,
char byte1,
char byte0 /* Ethernet address low order byte */
)
{
char bytes[6];
/* Save six bytes in NVRAM */
bytes[0] = byte5; bytes[1] = byte4; bytes[2] = byte3;
bytes[3] = byte2; bytes[4] = byte1; bytes[5] = byte0;
sysNvRamSet (bytes, 6, ENET_NVRAM_OFFSET);
return (OK);
}
#endif /* ETHERNET_ADR_SET */
再者最核心的是调用:sysNvRamSet;
/*****************************
*
* sysNvRamSet - write to non-volatile RAM
*
* This routine copies a specified string into non-volatile RAM.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamGet()
*/
STATUS sysNvRamSet
(
char *string, /* string to be copied into non-volatile RAM */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into non-volatile RAM */
)
{
char *NvBuf, *srcBuf;
FLASH flash;
STATUS result;
int index, buint8s;
void * blocks[1];
if ((offset < 0)
|| (strLen < 0)
|| ((offset + strLen) > NV_RAM_SIZE))
return ERROR;
/* get a copy of the buffer
* first, define a buffer large enough for a whole flash block
* We use memory normally assigned to the booted image.
*/
NvBuf = (char *)0x1000;
blocks[0]=(void *)NvBuf;
/* copy the contents of NVRAM into the buffer */
srcBuf = (char *)PARAM_SECTOR_ADDRESS;
for ( index = 0; index < (PARAM_SEC_SIZE - NV_RAM_SIZE); index++)
{
NvBuf[index] = srcBuf[index];
}
result = sysNvRamGet
(
&NvBuf[PARAM_SEC_SIZE - NV_RAM_SIZE], /* where to copy */
NV_RAM_SIZE - 1, /* maximum number of bytes to copy */
0 /* byte offset into non-volatile RAM */
);
/* copy the new parameters into the buffer */
while (strLen--)
{
NvBuf[PARAM_SEC_SIZE - NV_RAM_SIZE + offset] = *string;
string++, offset++;
}
flash.blockptr=(void *)blocks;
flash.blocksz = PARAM_SEC_SIZE;
flash.sector=PARAM_SEC;
flash.numblocks=1;
buint8s = am29xxxx_write((AM29XXXX *)ROM_BASE_ADRS, &flash, NULL, NULL);
if (buint8s != PARAM_SEC_SIZE)
{
printf("Flash programming error: %d uint8s of %d written!\n",
buint8s, PARAM_SEC_SIZE);
}
/* verify data */
for ( index = 0; index < (PARAM_SEC_SIZE); index++)
{
if ( NvBuf[index] != srcBuf[index])
{
result = ERROR;
goto exit;
}
}
exit:
return result;
}
Press any key to stop auto-boot...
7
在启动的时候输入N就可以修改MAC地址,
[VxWorks Boot]: N
Current Ethernet Address is: 00:a0:1e:52:75:88
Modify only the last 3 bytes (board unique portion) of Ethernet Address.
The first 3 bytes are fixed at manufacturer's default address block.
00- 00
a0- a0
1e- 1e
52- 52
75- 75
88- 88
New Ethernet Address is: 00:a0:1e:52:75:88
我就想要是在 VXWORKS启动后自己也调用sysNvRamSet函数,
但试了以下,
仔细研究了以下:sysNvRamSet函数里的东西发现:
char *NvBuf,
NvBuf = (char *)0x1000;
(char *)0x1000是什么不就是VXWORKS的启动地址么???
Attached TCP/IP interface to motfec0.
0x1fa5b00 (tNetTask): duplicate IP address 192.168.0.155 sent from ethernet addr
ess 00:04:
Warning: no netmask specified.
Attaching network interface lo0... done.
Loading... 845496 + 292816
Starting at 0x1000...?????
怎么能这样定义:
原来问题在这里:
把char *NvBuf,修改以下:
char NvBuf[64*1024], *srcBuf;/*
//NvBuf = (char *)0x1000;
这就不要了!这样就可以动态修改修改MAC地址了!
其实这sysNvRamSet还有好多的功能,
sysNvRamSet(bytes, 6, ENET_NVRAM_OFFSET);只要把ENET_
通过以下的函数读出来就可以:
/*****************************
*
* sysNvRamGet - get the contents of non-volatile RAM
*
* This routine copies the contents of non-volatile memory into a specified
* string. The string is terminated with an EOS.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamSet()
*/
STATUS sysNvRamGet
(
char *string, /* where to copy non-volatile RAM */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into non-volatile RAM */
)
{
char *read_ptr;
if ((strLen < 0) || (offset < 0 )
|| ((offset + strLen) > NV_RAM_SIZE))
return (ERROR);
read_ptr = (char *)offset; /* boot line begins at
while (strLen--)
{
*string = NV_RAM_READ (read_ptr);
string++, read_ptr++;
}
*string = EOS;
return (OK);
}
以上的函数MCF527X的BSP里就有的!
至于其他的平台大家自己参照吧!思路已经给出来了!
From: http://wenda.tianya.cn/wenda/thread?tid=1becad9302183473
局域网实现VLAN实例
局域网实现VLAN实例计算机网络技术的发展犹如戏剧舞台,你方唱罢我登台。从传统的以太网(10Mb/s)发展到快速以太网(100Mb/s)和千兆以 太网(1000Mb/s)也不过几年的时间,其迅猛的势头实在令人吃惊。而现在中大型规模网络建设中,以千兆三层交换机为核心的所谓"千兆主干跑、百兆到 桌面"的主流网络模型已不胜枚举。 现在,网络业界对"三层交换"和VLAN这两词已经不感到陌生了。
一、什么是三层交换和VLAN要回答这个问题我们还是先看看以太网的工作原理。以太网的工作原理是利用二进制位形成的一个个字节组合成一帧帧的数据(其实是一些电脉冲)在导线中进行传播。
首 先,以太网网段上需要进行数据传送的节点对导线进行监听,这个过程称为CSMA/CD(Carrier Sense Multiple Access with Collision Detection带有冲突监测的载波侦听多址访问)的载波侦听。如果,这时有另外的节点正在传送数据,监听节点将不得不等待,直到传送节点的传送任务结 束。如果某时恰好有两个工作站同时准备传送数据,以太网网段将发出"冲突"信号。这时,节点上所有的工作站都将检测到冲突信号,因为这时导线上的电压超出 了标准电压。这时以太网网段上的任何节点都要等冲突结束后才能够传送数据。也就是说在CSMA/CD方式下,在一个时间段,只有一个节点能够在导线上传送 数据。而转发以太网数据帧的联网设备是集线器,它是一层设备,传输效率比较低。冲突的产生降低了以太网的带宽,而且这种情况又是不可避免的。所以,当导线 上的节点越来越多后,冲突的数量将会增加。显而易见的解决方法是限制以太网导线上的节点,需要对网络进行物理分段。将网络进行物理分段的网络设备用到了网 桥与交换机。网桥和交换机的基本作用是只发送去往其他物理网段的信息。所以,如果所有的信息都只发往本地的物理网段,那么网桥和交换机上就没有信息通过。 这样可以有效减少网络上的冲突。网桥和交换机是基于目标MAC(介质访问控制)地址做出转发决定的,它们是二层设备。
我们已经知道了 以太网的缺点及物理网段中冲突的影响,现在,我们来看看另外一种导致网络降低运行速度的原因:广播。广播存在于所有的网络上,如果不对它们进行适当的控 制,它们便会充斥于整个网络,产生大量的网络通信。广播不仅消耗了带宽,而且也降低了用户工作站的处理效率。由于各种各样的原因,网络操作系统(NOS) 使用了广播,TCP/IP使用广播从IP地址中解析MAC地址,还使用广播通过RIP和IGRP协议进行宣告,所以,广播也是不可避免的。网桥和交换机将 对所有的广播信息进行转发,而路由器不会。所以,为了对广播进行控制,就必须使用路由器。路由器是基于第3层报头、目标IP寻址、目标IPX寻址或目标 Appletalk寻址做出转发决定。路由器是3层设备。
在这里,我们就容易理解三层交换技术了,通俗地讲,就是将路由与交换合二为 一的技术。路由器在对第一个数据流进行路由后,将会产生一个MAC地址与IP地址的映射表,当同样的数据流再次通过时,将根据此映射表直接从二层进行交换 而不是再次路由,提供线速性能,从而消除了路由器进行路由选择而造成网络的延迟,提高了数据包转发的效率。采用此技术的交换机我们常称为三层交换机。
那 么,什么是VLAN呢?VLAN(Virtual Local Area Network)就是虚拟局域网的意思。VLAN可以不考虑用户的物理位置,而根据功能、应用等因素将用户从逻辑上划分为一个个功能相对独立的工作组,每 个用户主机都连接在一个支持VLAN的交换机端口上并属于一个VLAN。同一个VLAN中的成员都共享广播,形成一个广播域,而不同VLAN之间广播信息 是相互隔离的。这样,将整个网络分割成多个不同的广播域(VLAN)。一般来说,如果一个VLAN里面的工作站发送一个广播,那么这个VLAN里面所有的 工作站都接收到这个广播,但是交换机不会将广播发送至其他VLAN上的任何一个端口。如果要将广播发送到其它的VLAN端口,就要用到三层交换机。
二、如何配置三层交换机创建VLAN
以下的介绍都是基于Cisco交换机的VLAN。Cisco的VLAN实现通常是以端口为中心的,与节点相连的端口将确定它所驻留的VLAN。将端口分配给VLAN的方式有两种,分别是静态的和动态的.
形成静态VLAN的过程是将端口强制性地分配给VLAN的过程。即我们先在VTP (VLAN Trunking Protocol)Server上建立VLAN,然后将每个端口分配给相应的VLAN的过程。这是我们创建VLAN最常用的方法。
动 态VLAN形成很简单,由具体的机器决定自己属于哪个VLAN。即我们先建立一个VMPS(VLAN Membership Policy Server)VLAN管理策略服务器,里面包含一个文本文件,文件中存有与VLAN映射的MAC地址表。交换机根据这个映射表决定将端口分配给何种 VLAN。这种方法有很大的优势,但创建数据库是一项非常艰苦而且非常繁琐的工作。
下面以实例说明如何在一个典型的快速以太局域网中实现VLAN。
所 谓典型局域网就是指由一台具备三层交换功能的核心交换机接几台分支交换机(不一定具备三层交换能力)。我们假设核心交换机名称为:COM;分支交换机分别 为:PAR1、PAR2、PAR3,分别通过Port 1的光线模块与核心交换机相连;并且假设VLAN名称分别为COUNTER、MARKET、MANAGING……
需要做的工作:
1、设置VTP DOMAIN(核心、分支交换机上都设置)
2、配置中继(核心、分支交换机上都设置)
3、创建VLAN(在server上设置)
4、将交换机端口划入VLAN
5、配置三层交换
1、设置VTP DOMAIN。 VTP DOMAIN 称为管理域。
交换VTP更新信息的所有交换机必须配置为相同的管理域。如果所有的交换机都以中继线相连,那么只要在核心交换机上设置一个管理域,网络上所有的交换机都加入该域,这样管理域里所有的交换机就能够了解彼此的VLAN列表。
COM#vlan database 进入VLAN配置模式
COM(vlan)#vtp domain COM 设置VTP管理域名称 COM
COM(vlan)#vtp server 设置交换机为服务器模式
PAR1#vlan database 进入VLAN配置模式
PAR1(vlan)#vtp domain COM 设置VTP管理域名称COM
PAR1(vlan)#vtp Client 设置交换机为客户端模式
PAR2#vlan database 进入VLAN配置模式
PAR2(vlan)#vtp domain COM 设置VTP管理域名称COM
PAR2(vlan)#vtp Client 设置交换机为客户端模式
PAR3#vlan database 进入VLAN配置模式
PAR3(vlan)#vtp domain COM 设置VTP管理域名称COM
PAR3(vlan)#vtp Client 设置交换机为客户端模式
注 意:这里设置核心交换机为Server模式是指允许在该交换机上创建、修改、删除VLAN及其他一些对整个VTP域的配置参数,同步本VTP域中其他交换 机传递来的最新的VLAN信息;Client模式是指本交换机不能创建、删除、修改VLAN配置,也不能在NVRAM中存储VLAN配置,但可同步由本 VTP域中其他交换机传递来的VLAN信息。
2、配置中继为了保证管理域能够覆盖所有的分支交换机,必须配置中继。
Cisco 交换机能够支持任何介质作为中继线,为了实现中继可使用其特有的ISL标签。ISL(Inter-Switch Link)是一个在交换机之间、交换机与路由器之间及交换机与服务器之间传递多个VLAN信息及VLAN数据流的协议,通过在交换机直接相连的端口配置 ISL封装,即可跨越交换机进行整个网络的VLAN分配和进行配置。
在核心交换机端配置如下:
COM(config)#interface gigabitEthernet 2/1
COM(config-if)#switchport
COM(config-if)#switchport trunk encapsulation isl 配置中继协议
COM(config-if)#switchport mode trunk
COM(config)#interface gigabitEthernet 2/2
COM(config-if)#switchport
COM(config-if)#switchport trunk encapsulation isl 配置中继协议
COM(config-if)#switchport mode trunk
COM(config)#interface gigabitEthernet 2/3
COM(config-if)#switchport
COM(config-if)#switchport trunk encapsulation isl 配置中继协议
COM(config-if)#switchport mode trunk
在分支交换机端配置如下:
PAR1(config)#interface gigabitEthernet 0/1
PAR1(config-if)#switchport mode trunk
PAR2(config)#interface gigabitEthernet 0/1
PAR2(config-if)#switchport mode trunk
PAR3(config)#interface gigabitEthernet 0/1
PAR3(config-if)#switchport mode trunk
……
此时,管理域算是设置完毕了。
3、创建VLAN一旦建立了管理域,就可以创建VLAN了。
COM(vlan)#Vlan 10 name COUNTER 创建了一个编号为10 名字为COUNTER的 VLAN
COM(vlan)#Vlan 11 name MARKET 创建了一个编号为11 名字为MARKET的 VLAN
COM(vlan)#Vlan 12 name MANAGING 创建了一个编号为12 名字为MANAGING的 VLAN
……
注 意,这里的VLAN是在核心交换机上建立的,其实,只要是在管理域中的任何一台VTP 属性为Server的交换机上建立VLAN,它就会通过VTP通告整个管理域中的所有的交换机。但如果要将具体的交换机端口划入某个VLAN,就必须在该 端口所属的交换机上进行设置。
4、将交换机端口划入VLAN
例如,要将PAR1、PAR2、PAR3……分支交换机的端口1划入COUNTER VLAN,端口2划入MARKET VLAN,端口3划入MANAGING VLAN……
PAR1(config)#interface fastEthernet 0/1 配置端口1
PAR1(config-if)#switchport access vlan 10 归属COUNTER VLAN
PAR1(config)#interface fastEthernet 0/2 配置端口2
PAR1(config-if)#switchport access vlan 11 归属MARKET VLAN
PAR1(config)#interface fastEthernet 0/3 配置端口3
PAR1(config-if)#switchport access vlan 12 归属MANAGING VLAN
PAR2(config)#interface fastEthernet 0/1 配置端口1
PAR2(config-if)#switchport access vlan 10 归属COUNTER VLAN
PAR2(config)#interface fastEthernet 0/2 配置端口2
PAR2(config-if)#switchport access vlan 11 归属MARKET VLAN
PAR2(config)#interface fastEthernet 0/3 配置端口3
PAR2(config-if)#switchport access vlan 12 归属MANAGING VLAN
PAR3(config)#interface fastEthernet 0/1 配置端口1
PAR3(config-if)#switchport access vlan 10 归属COUNTER VLAN
PAR3(config)#interface fastEthernet 0/2 配置端口2
PAR3(config-if)#switchport access vlan 11 归属MARKET VLAN
PAR3(config)#interface fastEthernet 0/3 配置端口3
PAR3(config-if)#switchport access vlan 12 归属MANAGING VLAN
……
5、配置三层交换
到 这里,VLAN已经基本划分完毕。但是,VLAN间如何实现三层(网络层)交换呢?这时就要给各VLAN分配网络(IP)地址了。给VLAN分配IP地址 分两种情况,其一,给VLAN所有的节点分配静态IP地址;其二,给VLAN所有的节点分配动态IP地址。下面就这两种情况分别介绍。
假设给VLAN COUNTER分配的接口Ip地址为172.16.58.1/24,网络地址为:172.16.58.0,
VLAN MARKET 分配的接口Ip地址为172.16.59.1/24,网络地址为:172.16.59.0,
VLAN MANAGING分配接口Ip地址为172.16.60.1/24, 网络地址为172.16.60.0
……
如果动态分配IP地址,则设网络上的DHCP服务器IP地址为172.16.1.11。
(1)给VLAN所有的节点分配静态IP地址。
首先在核心交换机上分别设置各VLAN的接口IP地址。核心交换机将vlan做为一种接口对待,就象路由器上的一样,如下所示:
COM(config)#interface vlan 10
COM(config-if)#ip address 172.16.58.1 255.255.255.0 VLAN10接口IP
COM(config)#interface vlan 11
COM(config-if)#ip address 172.16.59.1 255.255.255.0 VLAN11接口IP
COM(config)#interface vlan 12
COM(config-if)#ip address 172.16.60.1 255.255.255.0 VLAN12接口IP
……
再在各接入VLAN的计算机上设置与所属VLAN的网络地址一致的IP地址,并且把默认网关设置为该VLAN的接口地址。这样,所有的VLAN也可以互访了。
(2)给VLAN所有的节点分配动态IP地址。
首先在核心交换机上分别设置各VLAN的接口IP地址和同样的DHCP服务器的IP地址,如下所示:
COM(config)#interface vlan 10
COM(config-if)#ip address 172.16.58.1 255.255.255.0 VLAN10接口IP
COM(config-if)#ip helper-address 172.16.1.11 DHCP Server IP
COM(config)#interface vlan 11
COM(config-if)#ip address 172.16.59.1 255.255.255.0 VLAN11接口IP
COM(config-if)#ip helper-address 172.16.1.11 DHCP Server IP
COM(config)#interface vlan 12
COM(config-if)#ip address 172.16.60.1 255.255.255.0 VLAN12接口IP
COM(config-if)#ip helper-address 172.16.1.11 DHCP Server IP
……
再在DHCP服务器上设置网络地址分别为172.16.58.0,172.16.59.0,172.16.60.0的作用域,并将这些作用域的"路由器"选项设置为对应VLAN的接口IP地址。这样,可以保证所有的VLAN也可以互访了。
最后在各接入VLAN的计算机进行网络设置,将IP地址选项设置为自动获得IP地址即可。
三、总结
本文是笔者在实际工作中的一些总结。笔者力图用通俗易懂的文字来阐述创建VLAN的全过程。并且给出了详细的设置步骤,只要你对Cisco交换机的IOS有所了解,看懂本文并不难。按照本文所示的步骤一步一步地做,你完全可以给一个典型的快速以太网络建立多个VLAN。