Quagga路由软件安装与命令行结构分析.docx
《Quagga路由软件安装与命令行结构分析.docx》由会员分享,可在线阅读,更多相关《Quagga路由软件安装与命令行结构分析.docx(6页珍藏版)》请在冰豆网上搜索。
Quagga路由软件安装与命令行结构分析
Quagga路由软件安装与命令行结构分析一Quagga简介Quagga是一个路由软件套件,它提供了路由协议的TCP/IP的路由支持服务,如RIPv1,RIPv2的,RIPng,OSPFv2,OSPFv3,BGP-4的,和BGP–4。
此外本软件除了支持IPv4路由协议外,还支持IPv6路由协议。
Quagga是GNUZebra(由KunihiroIshiguro开发)的一个分支。
二Quagga基本结构quagga主要由bgpd、ripd、ripngd、ospfd、ospf6d、vtysh等几个服务(这些服务的名称被建立之后,被挂上Linux使用时,通常在服务的名称之后会加上一个d,这也就是daemon的命名规则),根据实际需要我们选用相应的服务。
但quagga中Vtysh(也就是quagga的shell)是实现每个daemon的集合。
Quagga包含一个核心守护进程zebra,它作为Unix底层核心的一个抽象层,表示为linux上的一些ZservAPI或LinuxQuagga客户端的TCP流。
这些LinuxQuagga客户端实现路由协议并和zebra守护程序交换路由更新信息。
其中Zserv客户端包括:
Ospfd(实现OSPFv2)ripd(实现RIPv1和RIPv2)ospf6d(实现OSPFv3(IPv6))Ripngd(实现RIPv3(IPv6))Bgpd(实现BGP4+(包括对组播地址族和IPv6地址族的支持)注:
【1】daemonUnix的术语,指一种在后台执行的程序。
网络的服务器功能也多为后台程序,一种没有被显式激活,但处于休眠状态,等待某种条件满足的程序。
守护程序,无交互后台程序,UNIX端口监督程序;【2】ZebraZebra是一个开源的TCP/IP路由软件,同CiscoInternet网络操作系统(IOS)类似。
它灵活而且具有强大的功能,可以处理路由信息协议(RIP)、开放式最短路径优先协议(OSPF)和(BGP)边界网关协议以及这些协议的所有变体。
zebra守护进程是实际的路由管理者,控制着其他模块;而且用户主要通过它进行交互。
我们最先需要配置Zebra守护进程。
启动某一服务则:
服务名-d(例如:
ripd-d)三任务要求1.ubuntu下guagga软件的安装2.熟悉使用guagga软件四详细阐述1.buntu下quagga软件的安装
(一)安装环境A.硬件环境:
WindowsxpB.软件环境:
虚拟机ubuntu10.04C.安装路由软件quagga-0.99.16
(二)quagga虚拟机与windows下共享文件A.在虚拟机安装好后,在windows下的某一一盘符(例如d)内建一个共享文件夹,把guagga源文件拷到共享文件夹(例如命名为linuxshare)里并解压。
B.在虚拟机主界面选择option选项中的sharefolders中,按照提示设置共享文件路径(例d:
\linuxshare)。
(三)quagga配置A.打开终端并以root用户进入B.安装guagga时要用到g++,ubuntu10.04没有安装须下载安装此软件包root@ubuntu:
/#apt-getinstallg++C.quagga解压代码放在/mnt/hgfs/linuxshare/root@ubuntu:
/#cd/mnt/hgfs/linuxshare/quagga-0.99.16D.root@/mnt/hgfs/linuxshare/quagga-0.99.16#./configure--disable-ripd--disable-ripngd--disable-ospfd--disable-ospf6d--disable-watchquagga--disable-doc--enable-user=root--enable-group=root--enable-zebra--enable-vtysh注:
①./configure是用来检测你的安装平台的目标特征的(比如它会检查是否有编辑器、函数库,CC或GCC等等),并根据配置信息生产相应的makefile,它是个shell脚本。
②./configure–h输入此命令会一一列出当前配置环境所有配置选项③此输入选项含义为,启用相应服务程序,并对不用的服务程序进行关闭,其中--enable-user=root--enable-group=root是限定quagg软件的使用权限。
④配置时易出现如下错误:
checkingforperl.../usr/bin/perlcheckingfortputsin-ltermcap...nocheckingfortputsin-ltinfo...nocheckingfortputsin-lcurses...nocheckingfortputsin-lncurses...nocheckingformainin-lreadline...noconfigure:
error:
vtyshneedslibreadlinebutwasnotfoundandusableonyoursystem解决方法:
看readline软件包是否安装是否安装ncurses安装包是否安装libncursesw-dev或libncursesw5-de软件包(四)quagga编译root@/mnt/hgfs/linuxshare/quagga-0.99.16#make注:
make是用编译命令,它从Makefile中读取信息(呼叫原始码、函数库、编辑器)进行编译。
(五)quagga安装root@/mnt/hgfs/linuxshare/quagga-0.99.16#makeinstall注:
makeinstall是安装命令,它也从Makefile中读取指令,安装到指定的位置。
(六)启动quagga的核心守护进程root@/mnt/hgfs/linuxshare/quagga-0.99.16#Zebra–d注:
a)说明quagga相应服务程序已经运行,只要是虚拟机的不重启或卸载(makeuninstall),他都会在后台运行。
b)可能有以下错误:
①-zebra:
errorwhileloadingsharedlibraries:
libzebra.so.0:
cannotopensharedobjectfile:
Nosuchfileordirectory解决方法:
在/usr/local/lib下有lrwxrwxrwx1rootrootlibzebra.so->libzebra.so.0.0.0lrwxrwxrwx1rootrootlibzebra.so.0->libzebra.so.0.0.0-rwxr-xr-x1rootrootlibzebra.so.0.0.0这可能是由于/lib库出现问题:
则root@ubuntu:
/usr/local/lib#cplibzebra.*/libroot@ubuntu:
/usr/local/lib#rmlibzebra.*②Startingzebra.vty_read_config:
failedtoopenconfigurationfile/usr/local/etc/zebra.conf:
Permissiondeniedcan'topenconfigurationfile[/usr/local/etc/quagga/zebra.conf解决方法:
可以看到/usr/local/etc/没有zebra.conf(它是存放zebra相关用户,密码信息等),但有zebra.conf.sampleroot@ubuntu:
/usr/local/etc#cpzebra.conf.samplezebra.conf(七)执行quagga的shell程序root@/mnt/hgfs/linuxshare/quagga-0.99.16#vtysh接着进入guagga的shell界面:
Hello,thisisQuagga(version0.99.16).Copyright1996-2005KunihiroIshiguro,etal.ubuntu#注:
在相应quagga相应服务启动之后,输入vtysh作用就是通过相应界面,输入命令行控制后台执行的相应操作。
2.熟悉使用quagga软件
(一)quagga软件命令行部分结构ripdAUTH_NODE,VIEW_NODE,cmd_elementcmdospdAUTH_ENABLE_NODE。
ENABLE_NODEcmd_element.。
quaggaosp6dCONFIG_NODE。
(zebra)。
cmd_elementcmdripngd。
HIDDENDEBUG_NODE,bgpdVTY_NODE①②③④Vtysh是quagga软件的一个shell,所有命令行由此输入执行。
①以上××_NODE、cmd_element、cmd是层层嵌套,储存在结构体struct_vector中数据结构如下:
/*structforvector*/struct_vector{unsignedintactive;/*numberofactiveslots*/unsignedintalloced;/*numberofallocatedslot*/void**index;/*indextodata*/①};typedefstruct_vector*vector;注释:
①此处二级指针index指向cmd_element和vecto数据结构。
②现逐层分析:
××_NODEa)××_NODE数据结构structcmd_node{enumnode_typenode;/*Nodeindex.*/constchar*prompt;/*Promptcharacteratvtyinterface.*/intvtysh;/*Isthisnode'sconfigurationgoestovtysh?
*/int(*func)(structvty*);/*Node'sconfigurationwritefunction*/vectorcmd_vector;/*Vectorofthisnode'scommandlist.*/};b)××_NODE定义枚举类型、enumnode_type{AUTH_NODE,/*Authenticationmodeofvtyinterface.*/VIEW_NODE,/*Viewnode.Defaultmodeofvtyinterface.*/AUTH_ENABLE_NODE,/*Authenticationmodeforchangeenable.*/ENABLE_NODE,/*Enablenode...}c)××_NODE赋初值(以view_node为例)staticstructcmd_nodeview_node={VIEW_NODE,"%s>",};vectorcmdvec=NULL;d)××_NODE初始化(把节点都放到(struct_vector)cmdvec数据结构中)(例:
install_node(&view_node,NULL);)voidinstall_node(structcmd_node*node,int(*func)(structvty*)){vector_set_index(cmdvec,node->node,node);⑴node->func=func;node->cmd_vector=vector_init(VECTOR_MIN_SIZE);⑵}注释:
⑴//把node节点存放cmdvec的indexnode->func=func;⑵//为node下cmd_vector分配vector结构,以存放③(cmd_element)③现逐层分析:
cmd_elementa)cmd_element数据结构structcmd_element{constchar*string;/*Commandspecificationbystring.*/int(*func)(structcmd_element*,structvty*,int,constchar*[]);constchar*doc;/*Documentationofthiscommand.*/intdaemon;/*Daemontowhichthiscommandbelong.*/vectorstrvec;/*Pointingouteachdescriptionvector.*/unsignedintcmdsize;/*Commandindexcount.*/char*config;/*Configurationstring*/vectorsubconfig;/*Subconfigurationstring*/u_charattr;/*Commandattributes*/};b)cmd_element初始化(把cmd_element放到××_NODE数据结构中)(例:
install_element(VIEW_NODE,&config_list_cmd);)voidinstall_element(enumnode_typentype,structcmd_element*cmd){structcmd_node*cnode;if(!
cmdvec)/*cmd_inithasn'tbeencalled*/return;cnode=vector_slot(cmdvec,ntype);⑴if(cnode==NULL){fprintf(stderr,"Commandnode%ddoesn'texist,pleasecheckit\n",ntype);exit
(1);}vector_set(cnode->cmd_vector,cmd);⑵if(cmd->strvec==NULL)cmd->strvec=cmd_make_descvec(cmd->string,cmd->doc);⑶cmd->cmdsize=cmd_cmdsize(cmd->strvec);⑷}注释:
⑴从cmdvec中把ntype类型节点对应的index找到⑵把cmd存放到cnode的cmd_vector中⑶md_make_descvec(cmd->string,cmd->doc)作用就是把string和doc存放在strvec,其逻辑结构为activeactive*cmdallocedactive*strstrvecalloced**indexalloced.**index....*cmd.*str**indexactivealloced**index...举例:
cmd->string为:
route-mapWORD(deny|permit)<1-65535>cmd->doc为:
createroute-maporenterroute-mapcommandmode\n""routemaptag\n""routemapdeniessetoperations\n""routemappermitssetoperations\n""sequencetoinsertto/deletefromexistingroute-mapentry\n"执行md_make_descvec(cmd->string,cmd->doc)函数后:
active=4active
(1)alloced
(1)*cmd:
route-mapactive(4)**index*str:
createroute-maporenterroute-map...strvealloced(>=4)active
(1)alloced
(1)**index**index*cmd:
WORD*str:
routemaptagactive
(2)*cmd:
denyalloced
(2)*str:
routemapdeniessetoperations**index*cmd:
permit*str:
routemappermitssetoperationsactive
(1)alloced
(1)**index*cmd:
<1-65535>*str:
sequencetoinsertto/deletefromexistingroute-mapentry⑷cmdsize表示cmd的大小,route-mapWORD(deny|permit)<1-65535>中cmdsize=4④cmd的定义(是通过宏来实现的)a)宏的数据结构#defineDEFUN(funcname,cmdname,cmdstr,helpstr)\DEFUN_CMD_FUNC_DECL(funcname)\⑴DEFUN_CMD_ELEMENT(funcname,cmdname,cmdstr,helpstr,0,0)\⑵DEFUN_CMD_FUNC_TEXT(funcname)⑶注释:
funcname:
命令的函数名cmdname:
命令名字cmdstr:
命令字符串helpstr:
帮助信息⑴声明添加命令的执行函数staticintfuncname(structcmd_element*,structvty*,int,constchar*[]);⑵给cmdname赋值structcmd_elementcmdname=\{\.string=cmdstr,\.func=funcname,\.doc=helpstr,\.attr=attrs,\.daemon=dnum,\};⑶给出命令函数名及函数参数staticintfuncname(structcmd_element*self__attribute__((unused)),\structvty*vty__attribute__((unused)),\intargc__attribute__((unused)),\constchar*argv[]__attribute__((unused)))b)应用举例:
/*Hostnameconfiguration*/DEFUN(config_hostname,hostname_cmd,"hostnameWORD","Setsystem'snetworkname\n""Thissystem'snetworkname\n"){if(!
isalpha((int)*argv[0])){vty_out(vty,"Pleasespecifystringstartingwithalphabet%s",VTY_NEWLINE);returnCMD_WARNING;}if(host.name)XFREE(MTYPE_HOST,host.name);host.name=XSTRDUP(MTYPE_HOST,argv[0]);returnCMD_SUCCESS;}替换相应宏的结果为:
⑴staticintconfig_hostname(structcmd_element*,structvty*,int,constchar*[]);⑵structcmd_elementhostname_cmd=\{\.string=hostnameWORD,\.func=config_hostname,\.doc=Setsystem'snetworkname\nThissystem'snetworkname\n,\.attr=0,\.daemon=0,\};⑶staticintconfig_hostname\(structcmd_element*self__attribute__((unused)),\structvty*vty__attribute__((unused)),\intargc__attribute__((unused)),\constchar*argv[]__attribute__((unused))){if(!
isalpha((int)*argv[0])){vty_out(vty,"Pleasespecifystringstartingwithalphabet%s",VTY_NEWLINE);returnCMD_WARNING;}if(host.name)XFREE(MTYPE_HOST,host.name);host.name=XSTRDUP(MTYPE_HOST,argv[0]);returnCMD_SUCCESS;}
(二)添加命令行1.定义命令#defineDEFUN(funcname,cmdname,cmdstr,helpstr)\DEFUN_CMD_FUNC_DECL(funcname)\DEFUN_CMD_ELEMENT(funcname,cmdname,cmdstr,helpstr,0,0)\DEFUN_CMD_FUNC_TEXT(funcname)2.命令初始化①添加命令的节点voidinstall_node(structcmd_node*node,int(*func)(structvty*))②添加命令到指定的节点voidinstall_element(enumnode_typentype,structcmd_element*cmd)(三)在vtysh(shell)下命令的执行A.在运行quagga开始,程序执行Vtysh_main();程序初始化后,最终在