123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101 |
- /* BGP routing information
- Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
- This file is part of GNU Zebra.
- GNU Zebra is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
- GNU Zebra is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Zebra; see the file COPYING. If not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
- #include <zebra.h>
- #include "prefix.h"
- #include "linklist.h"
- #include "memory.h"
- #include "command.h"
- #include "stream.h"
- #include "filter.h"
- #include "str.h"
- #include "log.h"
- #include "routemap.h"
- #include "buffer.h"
- #include "sockunion.h"
- #include "plist.h"
- #include "thread.h"
- #include "workqueue.h"
- #include "bgpd/bgpd.h"
- #include "bgpd/bgp_table.h"
- #include "bgpd/bgp_route.h"
- #include "bgpd/bgp_attr.h"
- #include "bgpd/bgp_debug.h"
- #include "bgpd/bgp_aspath.h"
- #include "bgpd/bgp_regex.h"
- #include "bgpd/bgp_community.h"
- #include "bgpd/bgp_ecommunity.h"
- #include "bgpd/bgp_clist.h"
- #include "bgpd/bgp_packet.h"
- #include "bgpd/bgp_filter.h"
- #include "bgpd/bgp_fsm.h"
- #include "bgpd/bgp_mplsvpn.h"
- #include "bgpd/bgp_nexthop.h"
- #include "bgpd/bgp_damp.h"
- #include "bgpd/bgp_advertise.h"
- #include "bgpd/bgp_zebra.h"
- #include "bgpd/bgp_vty.h"
- #include "bgpd/bgp_mpath.h"
- /* Extern from bgp_dump.c */
- extern const char *bgp_origin_str[];
- extern const char *bgp_origin_long_str[];
- static struct bgp_node *
- bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p,
- struct prefix_rd *prd)
- {
- struct bgp_node *rn;
- struct bgp_node *prn = NULL;
-
- assert (table);
- if (!table)
- return NULL;
-
- if (safi == SAFI_MPLS_VPN)
- {
- prn = bgp_node_get (table, (struct prefix *) prd);
- if (prn->info == NULL)
- prn->info = bgp_table_init (afi, safi);
- else
- bgp_unlock_node (prn);
- table = prn->info;
- }
- rn = bgp_node_get (table, p);
- if (safi == SAFI_MPLS_VPN)
- rn->prn = prn;
- return rn;
- }
- /* Allocate bgp_info_extra */
- static struct bgp_info_extra *
- bgp_info_extra_new (void)
- {
- struct bgp_info_extra *new;
- new = XCALLOC (MTYPE_BGP_ROUTE_EXTRA, sizeof (struct bgp_info_extra));
- return new;
- }
- static void
- bgp_info_extra_free (struct bgp_info_extra **extra)
- {
- if (extra && *extra)
- {
- if ((*extra)->damp_info)
- bgp_damp_info_free ((*extra)->damp_info, 0);
-
- (*extra)->damp_info = NULL;
-
- XFREE (MTYPE_BGP_ROUTE_EXTRA, *extra);
-
- *extra = NULL;
- }
- }
- /* Get bgp_info extra information for the given bgp_info, lazy allocated
- * if required.
- */
- struct bgp_info_extra *
- bgp_info_extra_get (struct bgp_info *ri)
- {
- if (!ri->extra)
- ri->extra = bgp_info_extra_new();
- return ri->extra;
- }
- /* Allocate new bgp info structure. */
- static struct bgp_info *
- bgp_info_new (void)
- {
- return XCALLOC (MTYPE_BGP_ROUTE, sizeof (struct bgp_info));
- }
- /* Free bgp route information. */
- static void
- bgp_info_free (struct bgp_info *binfo)
- {
- if (binfo->attr)
- bgp_attr_unintern (&binfo->attr);
-
- bgp_info_extra_free (&binfo->extra);
- bgp_info_mpath_free (&binfo->mpath);
- peer_unlock (binfo->peer); /* bgp_info peer reference */
- XFREE (MTYPE_BGP_ROUTE, binfo);
- }
- struct bgp_info *
- bgp_info_lock (struct bgp_info *binfo)
- {
- binfo->lock++;
- return binfo;
- }
- struct bgp_info *
- bgp_info_unlock (struct bgp_info *binfo)
- {
- assert (binfo && binfo->lock > 0);
- binfo->lock--;
-
- if (binfo->lock == 0)
- {
- #if 0
- zlog_debug ("%s: unlocked and freeing", __func__);
- zlog_backtrace (LOG_DEBUG);
- #endif
- bgp_info_free (binfo);
- return NULL;
- }
- #if 0
- if (binfo->lock == 1)
- {
- zlog_debug ("%s: unlocked to 1", __func__);
- zlog_backtrace (LOG_DEBUG);
- }
- #endif
-
- return binfo;
- }
- void
- bgp_info_add (struct bgp_node *rn, struct bgp_info *ri)
- {
- struct bgp_info *top;
- top = rn->info;
-
- ri->next = rn->info;
- ri->prev = NULL;
- if (top)
- top->prev = ri;
- rn->info = ri;
-
- bgp_info_lock (ri);
- bgp_lock_node (rn);
- peer_lock (ri->peer); /* bgp_info peer reference */
- }
- /* Do the actual removal of info from RIB, for use by bgp_process
- completion callback *only* */
- static void
- bgp_info_reap (struct bgp_node *rn, struct bgp_info *ri)
- {
- if (ri->next)
- ri->next->prev = ri->prev;
- if (ri->prev)
- ri->prev->next = ri->next;
- else
- rn->info = ri->next;
-
- bgp_info_mpath_dequeue (ri);
- bgp_info_unlock (ri);
- bgp_unlock_node (rn);
- }
- void
- bgp_info_delete (struct bgp_node *rn, struct bgp_info *ri)
- {
- bgp_info_set_flag (rn, ri, BGP_INFO_REMOVED);
- /* set of previous already took care of pcount */
- UNSET_FLAG (ri->flags, BGP_INFO_VALID);
- }
- /* undo the effects of a previous call to bgp_info_delete; typically
- called when a route is deleted and then quickly re-added before the
- deletion has been processed */
- static void
- bgp_info_restore (struct bgp_node *rn, struct bgp_info *ri)
- {
- bgp_info_unset_flag (rn, ri, BGP_INFO_REMOVED);
- /* unset of previous already took care of pcount */
- SET_FLAG (ri->flags, BGP_INFO_VALID);
- }
- /* Adjust pcount as required */
- static void
- bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
- {
- struct bgp_table *table;
- assert (rn && bgp_node_table (rn));
- assert (ri && ri->peer && ri->peer->bgp);
- table = bgp_node_table (rn);
- /* Ignore 'pcount' for RS-client tables */
- if (table->type != BGP_TABLE_MAIN
- || ri->peer == ri->peer->bgp->peer_self)
- return;
-
- if (BGP_INFO_HOLDDOWN (ri)
- && CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
- {
-
- UNSET_FLAG (ri->flags, BGP_INFO_COUNTED);
-
- /* slight hack, but more robust against errors. */
- if (ri->peer->pcount[table->afi][table->safi])
- ri->peer->pcount[table->afi][table->safi]--;
- else
- {
- zlog_warn ("%s: Asked to decrement 0 prefix count for peer %s",
- __func__, ri->peer->host);
- zlog_backtrace (LOG_WARNING);
- zlog_warn ("%s: Please report to Quagga bugzilla", __func__);
- }
- }
- else if (!BGP_INFO_HOLDDOWN (ri)
- && !CHECK_FLAG (ri->flags, BGP_INFO_COUNTED))
- {
- SET_FLAG (ri->flags, BGP_INFO_COUNTED);
- ri->peer->pcount[table->afi][table->safi]++;
- }
- }
- /* Set/unset bgp_info flags, adjusting any other state as needed.
- * This is here primarily to keep prefix-count in check.
- */
- void
- bgp_info_set_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
- {
- SET_FLAG (ri->flags, flag);
-
- /* early bath if we know it's not a flag that changes useability state */
- if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
- return;
-
- bgp_pcount_adjust (rn, ri);
- }
- void
- bgp_info_unset_flag (struct bgp_node *rn, struct bgp_info *ri, u_int32_t flag)
- {
- UNSET_FLAG (ri->flags, flag);
-
- /* early bath if we know it's not a flag that changes useability state */
- if (!CHECK_FLAG (flag, BGP_INFO_VALID|BGP_INFO_UNUSEABLE))
- return;
-
- bgp_pcount_adjust (rn, ri);
- }
- /* Get MED value. If MED value is missing and "bgp bestpath
- missing-as-worst" is specified, treat it as the worst value. */
- static u_int32_t
- bgp_med_value (struct attr *attr, struct bgp *bgp)
- {
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
- return attr->med;
- else
- {
- if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
- return BGP_MED_MAX;
- else
- return 0;
- }
- }
- /* Compare two bgp route entity. br is preferable then return 1. */
- static int
- bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
- int *paths_eq)
- {
- struct attr *newattr, *existattr;
- struct attr_extra *newattre, *existattre;
- bgp_peer_sort_t new_sort;
- bgp_peer_sort_t exist_sort;
- u_int32_t new_pref;
- u_int32_t exist_pref;
- u_int32_t new_med;
- u_int32_t exist_med;
- u_int32_t new_weight;
- u_int32_t exist_weight;
- uint32_t newm, existm;
- struct in_addr new_id;
- struct in_addr exist_id;
- int new_cluster;
- int exist_cluster;
- int internal_as_route;
- int confed_as_route;
- int ret;
- *paths_eq = 0;
- /* 0. Null check. */
- if (new == NULL)
- return 0;
- if (exist == NULL)
- return 1;
- newattr = new->attr;
- existattr = exist->attr;
- newattre = newattr->extra;
- existattre = existattr->extra;
- /* 1. Weight check. */
- new_weight = exist_weight = 0;
- if (newattre)
- new_weight = newattre->weight;
- if (existattre)
- exist_weight = existattre->weight;
- if (new_weight > exist_weight)
- return 1;
- if (new_weight < exist_weight)
- return 0;
- /* 2. Local preference check. */
- new_pref = exist_pref = bgp->default_local_pref;
- if (newattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- new_pref = newattr->local_pref;
- if (existattr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- exist_pref = existattr->local_pref;
- if (new_pref > exist_pref)
- return 1;
- if (new_pref < exist_pref)
- return 0;
- /* 3. Local route check. We prefer:
- * - BGP_ROUTE_STATIC
- * - BGP_ROUTE_AGGREGATE
- * - BGP_ROUTE_REDISTRIBUTE
- */
- if (! (new->sub_type == BGP_ROUTE_NORMAL))
- return 1;
- if (! (exist->sub_type == BGP_ROUTE_NORMAL))
- return 0;
- /* 4. AS path length check. */
- if (! bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
- {
- int exist_hops = aspath_count_hops (existattr->aspath);
- int exist_confeds = aspath_count_confeds (existattr->aspath);
-
- if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
- {
- int aspath_hops;
-
- aspath_hops = aspath_count_hops (newattr->aspath);
- aspath_hops += aspath_count_confeds (newattr->aspath);
-
- if ( aspath_hops < (exist_hops + exist_confeds))
- return 1;
- if ( aspath_hops > (exist_hops + exist_confeds))
- return 0;
- }
- else
- {
- int newhops = aspath_count_hops (newattr->aspath);
-
- if (newhops < exist_hops)
- return 1;
- if (newhops > exist_hops)
- return 0;
- }
- }
- /* 5. Origin check. */
- if (newattr->origin < existattr->origin)
- return 1;
- if (newattr->origin > existattr->origin)
- return 0;
- /* 6. MED check. */
- internal_as_route = (aspath_count_hops (newattr->aspath) == 0
- && aspath_count_hops (existattr->aspath) == 0);
- confed_as_route = (aspath_count_confeds (newattr->aspath) > 0
- && aspath_count_confeds (existattr->aspath) > 0
- && aspath_count_hops (newattr->aspath) == 0
- && aspath_count_hops (existattr->aspath) == 0);
-
- if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
- || (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
- && confed_as_route)
- || aspath_cmp_left (newattr->aspath, existattr->aspath)
- || aspath_cmp_left_confed (newattr->aspath, existattr->aspath)
- || internal_as_route)
- {
- new_med = bgp_med_value (new->attr, bgp);
- exist_med = bgp_med_value (exist->attr, bgp);
- if (new_med < exist_med)
- return 1;
- if (new_med > exist_med)
- return 0;
- }
- /* 7. Peer type check. */
- new_sort = new->peer->sort;
- exist_sort = exist->peer->sort;
- if (new_sort == BGP_PEER_EBGP
- && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED))
- return 1;
- if (exist_sort == BGP_PEER_EBGP
- && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED))
- return 0;
- /* 8. IGP metric check. */
- newm = existm = 0;
- if (new->extra)
- newm = new->extra->igpmetric;
- if (exist->extra)
- existm = exist->extra->igpmetric;
- if (newm < existm)
- ret = 1;
- if (newm > existm)
- ret = 0;
- /* 9. Maximum path check. */
- if (newm == existm)
- {
- if (new->peer->sort == BGP_PEER_IBGP)
- {
- if (aspath_cmp (new->attr->aspath, exist->attr->aspath))
- *paths_eq = 1;
- }
- else if (new->peer->as == exist->peer->as)
- *paths_eq = 1;
- }
- else
- {
- /*
- * TODO: If unequal cost ibgp multipath is enabled we can
- * mark the paths as equal here instead of returning
- */
- return ret;
- }
- /* 10. If both paths are external, prefer the path that was received
- first (the oldest one). This step minimizes route-flap, since a
- newer path won't displace an older one, even if it was the
- preferred route based on the additional decision criteria below. */
- if (! bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID)
- && new_sort == BGP_PEER_EBGP
- && exist_sort == BGP_PEER_EBGP)
- {
- if (CHECK_FLAG (new->flags, BGP_INFO_SELECTED))
- return 1;
- if (CHECK_FLAG (exist->flags, BGP_INFO_SELECTED))
- return 0;
- }
- /* 11. Rourter-ID comparision. */
- if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- new_id.s_addr = newattre->originator_id.s_addr;
- else
- new_id.s_addr = new->peer->remote_id.s_addr;
- if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- exist_id.s_addr = existattre->originator_id.s_addr;
- else
- exist_id.s_addr = exist->peer->remote_id.s_addr;
- if (ntohl (new_id.s_addr) < ntohl (exist_id.s_addr))
- return 1;
- if (ntohl (new_id.s_addr) > ntohl (exist_id.s_addr))
- return 0;
- /* 12. Cluster length comparision. */
- new_cluster = exist_cluster = 0;
- if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- new_cluster = newattre->cluster->length;
- if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- exist_cluster = existattre->cluster->length;
- if (new_cluster < exist_cluster)
- return 1;
- if (new_cluster > exist_cluster)
- return 0;
- /* 13. Neighbor address comparision. */
- ret = sockunion_cmp (new->peer->su_remote, exist->peer->su_remote);
- if (ret == 1)
- return 0;
- if (ret == -1)
- return 1;
- return 1;
- }
- static enum filter_type
- bgp_input_filter (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi)
- {
- struct bgp_filter *filter;
- filter = &peer->filter[afi][safi];
- #define FILTER_EXIST_WARN(F,f,filter) \
- if (BGP_DEBUG (update, UPDATE_IN) \
- && !(F ## _IN (filter))) \
- plog_warn (peer->log, "%s: Could not find configured input %s-list %s!", \
- peer->host, #f, F ## _IN_NAME(filter));
-
- if (DISTRIBUTE_IN_NAME (filter)) {
- FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
-
- if (access_list_apply (DISTRIBUTE_IN (filter), p) == FILTER_DENY)
- return FILTER_DENY;
- }
- if (PREFIX_LIST_IN_NAME (filter)) {
- FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
-
- if (prefix_list_apply (PREFIX_LIST_IN (filter), p) == PREFIX_DENY)
- return FILTER_DENY;
- }
-
- if (FILTER_LIST_IN_NAME (filter)) {
- FILTER_EXIST_WARN(FILTER_LIST, as, filter);
-
- if (as_list_apply (FILTER_LIST_IN (filter), attr->aspath)== AS_FILTER_DENY)
- return FILTER_DENY;
- }
-
- return FILTER_PERMIT;
- #undef FILTER_EXIST_WARN
- }
- static enum filter_type
- bgp_output_filter (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi)
- {
- struct bgp_filter *filter;
- filter = &peer->filter[afi][safi];
- #define FILTER_EXIST_WARN(F,f,filter) \
- if (BGP_DEBUG (update, UPDATE_OUT) \
- && !(F ## _OUT (filter))) \
- plog_warn (peer->log, "%s: Could not find configured output %s-list %s!", \
- peer->host, #f, F ## _OUT_NAME(filter));
- if (DISTRIBUTE_OUT_NAME (filter)) {
- FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
-
- if (access_list_apply (DISTRIBUTE_OUT (filter), p) == FILTER_DENY)
- return FILTER_DENY;
- }
- if (PREFIX_LIST_OUT_NAME (filter)) {
- FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
-
- if (prefix_list_apply (PREFIX_LIST_OUT (filter), p) == PREFIX_DENY)
- return FILTER_DENY;
- }
- if (FILTER_LIST_OUT_NAME (filter)) {
- FILTER_EXIST_WARN(FILTER_LIST, as, filter);
-
- if (as_list_apply (FILTER_LIST_OUT (filter), attr->aspath) == AS_FILTER_DENY)
- return FILTER_DENY;
- }
- return FILTER_PERMIT;
- #undef FILTER_EXIST_WARN
- }
- /* If community attribute includes no_export then return 1. */
- static int
- bgp_community_filter (struct peer *peer, struct attr *attr)
- {
- if (attr->community)
- {
- /* NO_ADVERTISE check. */
- if (community_include (attr->community, COMMUNITY_NO_ADVERTISE))
- return 1;
- /* NO_EXPORT check. */
- if (peer->sort == BGP_PEER_EBGP &&
- community_include (attr->community, COMMUNITY_NO_EXPORT))
- return 1;
- /* NO_EXPORT_SUBCONFED check. */
- if (peer->sort == BGP_PEER_EBGP
- || peer->sort == BGP_PEER_CONFED)
- if (community_include (attr->community, COMMUNITY_NO_EXPORT_SUBCONFED))
- return 1;
- }
- return 0;
- }
- /* Route reflection loop check. */
- static int
- bgp_cluster_filter (struct peer *peer, struct attr *attr)
- {
- struct in_addr cluster_id;
- if (attr->extra && attr->extra->cluster)
- {
- if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
- cluster_id = peer->bgp->cluster_id;
- else
- cluster_id = peer->bgp->router_id;
-
- if (cluster_loop_check (attr->extra->cluster, cluster_id))
- return 1;
- }
- return 0;
- }
- static int
- bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi)
- {
- struct bgp_filter *filter;
- struct bgp_info info;
- route_map_result_t ret;
- filter = &peer->filter[afi][safi];
- /* Apply default weight value. */
- if (peer->weight)
- (bgp_attr_extra_get (attr))->weight = peer->weight;
- /* Route map apply. */
- if (ROUTE_MAP_IN_NAME (filter))
- {
- /* Duplicate current value to new strucutre for modification. */
- info.peer = peer;
- info.attr = attr;
- SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IN);
- /* Apply BGP route map to the attribute. */
- ret = route_map_apply (ROUTE_MAP_IN (filter), p, RMAP_BGP, &info);
- peer->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- /* Free newly generated AS path and community by route-map. */
- bgp_attr_flush (attr);
- return RMAP_DENY;
- }
- }
- return RMAP_PERMIT;
- }
- static int
- bgp_export_modifier (struct peer *rsclient, struct peer *peer,
- struct prefix *p, struct attr *attr, afi_t afi, safi_t safi)
- {
- struct bgp_filter *filter;
- struct bgp_info info;
- route_map_result_t ret;
- filter = &peer->filter[afi][safi];
- /* Route map apply. */
- if (ROUTE_MAP_EXPORT_NAME (filter))
- {
- /* Duplicate current value to new strucutre for modification. */
- info.peer = rsclient;
- info.attr = attr;
- SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_EXPORT);
- /* Apply BGP route map to the attribute. */
- ret = route_map_apply (ROUTE_MAP_EXPORT (filter), p, RMAP_BGP, &info);
- rsclient->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- /* Free newly generated AS path and community by route-map. */
- bgp_attr_flush (attr);
- return RMAP_DENY;
- }
- }
- return RMAP_PERMIT;
- }
- static int
- bgp_import_modifier (struct peer *rsclient, struct peer *peer,
- struct prefix *p, struct attr *attr, afi_t afi, safi_t safi)
- {
- struct bgp_filter *filter;
- struct bgp_info info;
- route_map_result_t ret;
- filter = &rsclient->filter[afi][safi];
- /* Apply default weight value. */
- if (peer->weight)
- (bgp_attr_extra_get (attr))->weight = peer->weight;
- /* Route map apply. */
- if (ROUTE_MAP_IMPORT_NAME (filter))
- {
- /* Duplicate current value to new strucutre for modification. */
- info.peer = peer;
- info.attr = attr;
- SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_IMPORT);
- /* Apply BGP route map to the attribute. */
- ret = route_map_apply (ROUTE_MAP_IMPORT (filter), p, RMAP_BGP, &info);
- peer->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- /* Free newly generated AS path and community by route-map. */
- bgp_attr_flush (attr);
- return RMAP_DENY;
- }
- }
- return RMAP_PERMIT;
- }
- static int
- bgp_announce_check (struct bgp_info *ri, struct peer *peer, struct prefix *p,
- struct attr *attr, afi_t afi, safi_t safi)
- {
- int ret;
- char buf[SU_ADDRSTRLEN];
- struct bgp_filter *filter;
- struct peer *from;
- struct bgp *bgp;
- int transparent;
- int reflect;
- struct attr *riattr;
- from = ri->peer;
- filter = &peer->filter[afi][safi];
- bgp = peer->bgp;
- riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
-
- if (DISABLE_BGP_ANNOUNCE)
- return 0;
- /* Do not send announces to RS-clients from the 'normal' bgp_table. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- return 0;
- /* Do not send back route to sender. */
- if (from == peer)
- return 0;
- /* If peer's id and route's nexthop are same. draft-ietf-idr-bgp4-23 5.1.3 */
- if (p->family == AF_INET
- && IPV4_ADDR_SAME(&peer->remote_id, &riattr->nexthop))
- return 0;
- #ifdef HAVE_IPV6
- if (p->family == AF_INET6
- && IPV6_ADDR_SAME(&peer->remote_id, &riattr->nexthop))
- return 0;
- #endif
- /* Aggregate-address suppress check. */
- if (ri->extra && ri->extra->suppress)
- if (! UNSUPPRESS_MAP_NAME (filter))
- return 0;
- /* Default route check. */
- if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))
- {
- if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
- return 0;
- #ifdef HAVE_IPV6
- else if (p->family == AF_INET6 && p->prefixlen == 0)
- return 0;
- #endif /* HAVE_IPV6 */
- }
- /* Transparency check. */
- if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
- && CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- transparent = 1;
- else
- transparent = 0;
- /* If community is not disabled check the no-export and local. */
- if (! transparent && bgp_community_filter (peer, riattr))
- return 0;
- /* If the attribute has originator-id and it is same as remote
- peer's id. */
- if (riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
- {
- if (IPV4_ADDR_SAME (&peer->remote_id, &riattr->extra->originator_id))
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d originator-id is same as remote router-id",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- return 0;
- }
- }
-
- /* ORF prefix-list filter check */
- if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
- && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
- if (peer->orf_plist[afi][safi])
- {
- if (prefix_list_apply (peer->orf_plist[afi][safi], p) == PREFIX_DENY)
- return 0;
- }
- /* Output filter check. */
- if (bgp_output_filter (peer, p, riattr, afi, safi) == FILTER_DENY)
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d is filtered",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- return 0;
- }
- #ifdef BGP_SEND_ASPATH_CHECK
- /* AS path loop check. */
- if (aspath_loop_check (riattr->aspath, peer->as))
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- peer->host, peer->as);
- return 0;
- }
- #endif /* BGP_SEND_ASPATH_CHECK */
- /* If we're a CONFED we need to loop check the CONFED ID too */
- if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
- {
- if (aspath_loop_check(riattr->aspath, bgp->confed_id))
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (peer->log, LOG_DEBUG,
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- peer->host,
- bgp->confed_id);
- return 0;
- }
- }
- /* Route-Reflect check. */
- if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
- reflect = 1;
- else
- reflect = 0;
- /* IBGP reflection check. */
- if (reflect)
- {
- /* A route from a Client peer. */
- if (CHECK_FLAG (from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
- {
- /* Reflect to all the Non-Client peers and also to the
- Client peers other than the originator. Originator check
- is already done. So there is noting to do. */
- /* no bgp client-to-client reflection check. */
- if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
- if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
- return 0;
- }
- else
- {
- /* A route from a Non-client peer. Reflect to all other
- clients. */
- if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
- return 0;
- }
- }
-
- /* For modify attribute, copy it to temporary structure. */
- bgp_attr_dup (attr, riattr);
-
- /* If local-preference is not set. */
- if ((peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED)
- && (! (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))))
- {
- attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF);
- attr->local_pref = bgp->default_local_pref;
- }
- /* Remove MED if its an EBGP peer - will get overwritten by route-maps */
- if (peer->sort == BGP_PEER_EBGP
- && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
- {
- if (ri->peer != bgp->peer_self && ! transparent
- && ! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
- attr->flag &= ~(ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC));
- }
- /* next-hop-set */
- if (transparent || reflect
- || (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
- && ((p->family == AF_INET && attr->nexthop.s_addr)
- #ifdef HAVE_IPV6
- || (p->family == AF_INET6 &&
- ! IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
- #endif /* HAVE_IPV6 */
- )))
- {
- /* NEXT-HOP Unchanged. */
- }
- else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_SELF)
- || (p->family == AF_INET && attr->nexthop.s_addr == 0)
- #ifdef HAVE_IPV6
- || (p->family == AF_INET6 &&
- IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
- #endif /* HAVE_IPV6 */
- || (peer->sort == BGP_PEER_EBGP
- && bgp_multiaccess_check_v4 (attr->nexthop, peer->host) == 0))
- {
- /* Set IPv4 nexthop. */
- if (p->family == AF_INET)
- {
- if (safi == SAFI_MPLS_VPN)
- memcpy (&attr->extra->mp_nexthop_global_in, &peer->nexthop.v4,
- IPV4_MAX_BYTELEN);
- else
- memcpy (&attr->nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
- }
- #ifdef HAVE_IPV6
- /* Set IPv6 nexthop. */
- if (p->family == AF_INET6)
- {
- /* IPv6 global nexthop must be included. */
- memcpy (&attr->extra->mp_nexthop_global, &peer->nexthop.v6_global,
- IPV6_MAX_BYTELEN);
- attr->extra->mp_nexthop_len = 16;
- }
- #endif /* HAVE_IPV6 */
- }
- #ifdef HAVE_IPV6
- if (p->family == AF_INET6)
- {
- /* Left nexthop_local unchanged if so configured. */
- if ( CHECK_FLAG (peer->af_flags[afi][safi],
- PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) )
- {
- if ( IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_local) )
- attr->extra->mp_nexthop_len=32;
- else
- attr->extra->mp_nexthop_len=16;
- }
- /* Default nexthop_local treatment for non-RS-Clients */
- else
- {
- /* Link-local address should not be transit to different peer. */
- attr->extra->mp_nexthop_len = 16;
- /* Set link-local address for shared network peer. */
- if (peer->shared_network
- && ! IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
- {
- memcpy (&attr->extra->mp_nexthop_local, &peer->nexthop.v6_local,
- IPV6_MAX_BYTELEN);
- attr->extra->mp_nexthop_len = 32;
- }
- /* If bgpd act as BGP-4+ route-reflector, do not send link-local
- address.*/
- if (reflect)
- attr->extra->mp_nexthop_len = 16;
- /* If BGP-4+ link-local nexthop is not link-local nexthop. */
- if (! IN6_IS_ADDR_LINKLOCAL (&peer->nexthop.v6_local))
- attr->extra->mp_nexthop_len = 16;
- }
- }
- #endif /* HAVE_IPV6 */
- /* If this is EBGP peer and remove-private-AS is set. */
- if (peer->sort == BGP_PEER_EBGP
- && peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
- && aspath_private_as_check (attr->aspath))
- attr->aspath = aspath_empty_get ();
- /* Route map & unsuppress-map apply. */
- if (ROUTE_MAP_OUT_NAME (filter)
- || (ri->extra && ri->extra->suppress) )
- {
- struct bgp_info info;
- struct attr dummy_attr;
- struct attr_extra dummy_extra;
- dummy_attr.extra = &dummy_extra;
- info.peer = peer;
- info.attr = attr;
- /* The route reflector is not allowed to modify the attributes
- of the reflected IBGP routes. */
- if (from->sort == BGP_PEER_IBGP
- && peer->sort == BGP_PEER_IBGP)
- {
- bgp_attr_dup (&dummy_attr, attr);
- info.attr = &dummy_attr;
- }
- SET_FLAG (peer->rmap_type, PEER_RMAP_TYPE_OUT);
- if (ri->extra && ri->extra->suppress)
- ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info);
- else
- ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info);
- peer->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- bgp_attr_flush (attr);
- return 0;
- }
- }
- return 1;
- }
- static int
- bgp_announce_check_rsclient (struct bgp_info *ri, struct peer *rsclient,
- struct prefix *p, struct attr *attr, afi_t afi, safi_t safi)
- {
- int ret;
- char buf[SU_ADDRSTRLEN];
- struct bgp_filter *filter;
- struct bgp_info info;
- struct peer *from;
- struct attr *riattr;
- from = ri->peer;
- filter = &rsclient->filter[afi][safi];
- riattr = bgp_info_mpath_count (ri) ? bgp_info_mpath_attr (ri) : ri->attr;
- if (DISABLE_BGP_ANNOUNCE)
- return 0;
- /* Do not send back route to sender. */
- if (from == rsclient)
- return 0;
- /* Aggregate-address suppress check. */
- if (ri->extra && ri->extra->suppress)
- if (! UNSUPPRESS_MAP_NAME (filter))
- return 0;
- /* Default route check. */
- if (CHECK_FLAG (rsclient->af_sflags[afi][safi],
- PEER_STATUS_DEFAULT_ORIGINATE))
- {
- if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
- return 0;
- #ifdef HAVE_IPV6
- else if (p->family == AF_INET6 && p->prefixlen == 0)
- return 0;
- #endif /* HAVE_IPV6 */
- }
- /* If the attribute has originator-id and it is same as remote
- peer's id. */
- if (riattr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))
- {
- if (IPV4_ADDR_SAME (&rsclient->remote_id,
- &riattr->extra->originator_id))
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (rsclient->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d originator-id is same as remote router-id",
- rsclient->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- return 0;
- }
- }
- /* ORF prefix-list filter check */
- if (CHECK_FLAG (rsclient->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
- && (CHECK_FLAG (rsclient->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
- || CHECK_FLAG (rsclient->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
- if (rsclient->orf_plist[afi][safi])
- {
- if (prefix_list_apply (rsclient->orf_plist[afi][safi], p) == PREFIX_DENY)
- return 0;
- }
- /* Output filter check. */
- if (bgp_output_filter (rsclient, p, riattr, afi, safi) == FILTER_DENY)
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (rsclient->log, LOG_DEBUG,
- "%s [Update:SEND] %s/%d is filtered",
- rsclient->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- return 0;
- }
- #ifdef BGP_SEND_ASPATH_CHECK
- /* AS path loop check. */
- if (aspath_loop_check (riattr->aspath, rsclient->as))
- {
- if (BGP_DEBUG (filter, FILTER))
- zlog (rsclient->log, LOG_DEBUG,
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- rsclient->host, rsclient->as);
- return 0;
- }
- #endif /* BGP_SEND_ASPATH_CHECK */
- /* For modify attribute, copy it to temporary structure. */
- bgp_attr_dup (attr, riattr);
- /* next-hop-set */
- if ((p->family == AF_INET && attr->nexthop.s_addr == 0)
- #ifdef HAVE_IPV6
- || (p->family == AF_INET6 &&
- IN6_IS_ADDR_UNSPECIFIED(&attr->extra->mp_nexthop_global))
- #endif /* HAVE_IPV6 */
- )
- {
- /* Set IPv4 nexthop. */
- if (p->family == AF_INET)
- {
- if (safi == SAFI_MPLS_VPN)
- memcpy (&attr->extra->mp_nexthop_global_in, &rsclient->nexthop.v4,
- IPV4_MAX_BYTELEN);
- else
- memcpy (&attr->nexthop, &rsclient->nexthop.v4, IPV4_MAX_BYTELEN);
- }
- #ifdef HAVE_IPV6
- /* Set IPv6 nexthop. */
- if (p->family == AF_INET6)
- {
- /* IPv6 global nexthop must be included. */
- memcpy (&attr->extra->mp_nexthop_global, &rsclient->nexthop.v6_global,
- IPV6_MAX_BYTELEN);
- attr->extra->mp_nexthop_len = 16;
- }
- #endif /* HAVE_IPV6 */
- }
- #ifdef HAVE_IPV6
- if (p->family == AF_INET6)
- {
- struct attr_extra *attre = attr->extra;
- /* Left nexthop_local unchanged if so configured. */
- if ( CHECK_FLAG (rsclient->af_flags[afi][safi],
- PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED) )
- {
- if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) )
- attre->mp_nexthop_len=32;
- else
- attre->mp_nexthop_len=16;
- }
-
- /* Default nexthop_local treatment for RS-Clients */
- else
- {
- /* Announcer and RS-Client are both in the same network */
- if (rsclient->shared_network && from->shared_network &&
- (rsclient->ifindex == from->ifindex))
- {
- if ( IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local) )
- attre->mp_nexthop_len=32;
- else
- attre->mp_nexthop_len=16;
- }
- /* Set link-local address for shared network peer. */
- else if (rsclient->shared_network
- && IN6_IS_ADDR_LINKLOCAL (&rsclient->nexthop.v6_local))
- {
- memcpy (&attre->mp_nexthop_local, &rsclient->nexthop.v6_local,
- IPV6_MAX_BYTELEN);
- attre->mp_nexthop_len = 32;
- }
- else
- attre->mp_nexthop_len = 16;
- }
- }
- #endif /* HAVE_IPV6 */
- /* If this is EBGP peer and remove-private-AS is set. */
- if (rsclient->sort == BGP_PEER_EBGP
- && peer_af_flag_check (rsclient, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
- && aspath_private_as_check (attr->aspath))
- attr->aspath = aspath_empty_get ();
- /* Route map & unsuppress-map apply. */
- if (ROUTE_MAP_OUT_NAME (filter) || (ri->extra && ri->extra->suppress) )
- {
- info.peer = rsclient;
- info.attr = attr;
- SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_OUT);
- if (ri->extra && ri->extra->suppress)
- ret = route_map_apply (UNSUPPRESS_MAP (filter), p, RMAP_BGP, &info);
- else
- ret = route_map_apply (ROUTE_MAP_OUT (filter), p, RMAP_BGP, &info);
- rsclient->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- bgp_attr_flush (attr);
- return 0;
- }
- }
- return 1;
- }
- struct bgp_info_pair
- {
- struct bgp_info *old;
- struct bgp_info *new;
- };
- static void
- bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
- struct bgp_maxpaths_cfg *mpath_cfg,
- struct bgp_info_pair *result)
- {
- struct bgp_info *new_select;
- struct bgp_info *old_select;
- struct bgp_info *ri;
- struct bgp_info *ri1;
- struct bgp_info *ri2;
- struct bgp_info *nextri = NULL;
- int paths_eq, do_mpath;
- struct list mp_list;
- bgp_mp_list_init (&mp_list);
- do_mpath = (mpath_cfg->maxpaths_ebgp != BGP_DEFAULT_MAXPATHS ||
- mpath_cfg->maxpaths_ibgp != BGP_DEFAULT_MAXPATHS);
- /* bgp deterministic-med */
- new_select = NULL;
- if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
- for (ri1 = rn->info; ri1; ri1 = ri1->next)
- {
- if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK))
- continue;
- if (BGP_INFO_HOLDDOWN (ri1))
- continue;
- new_select = ri1;
- if (do_mpath)
- bgp_mp_list_add (&mp_list, ri1);
- old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL;
- if (ri1->next)
- for (ri2 = ri1->next; ri2; ri2 = ri2->next)
- {
- if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK))
- continue;
- if (BGP_INFO_HOLDDOWN (ri2))
- continue;
- if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath)
- || aspath_cmp_left_confed (ri1->attr->aspath,
- ri2->attr->aspath))
- {
- if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED))
- old_select = ri2;
- if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq))
- {
- bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
- new_select = ri2;
- if (do_mpath && !paths_eq)
- {
- bgp_mp_list_clear (&mp_list);
- bgp_mp_list_add (&mp_list, ri2);
- }
- }
- if (do_mpath && paths_eq)
- bgp_mp_list_add (&mp_list, ri2);
- bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK);
- }
- }
- bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK);
- bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
- bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
- bgp_mp_list_clear (&mp_list);
- }
- /* Check old selected route and new selected route. */
- old_select = NULL;
- new_select = NULL;
- for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); ri = nextri)
- {
- if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
- old_select = ri;
- if (BGP_INFO_HOLDDOWN (ri))
- {
- /* reap REMOVED routes, if needs be
- * selected route must stay for a while longer though
- */
- if (CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
- && (ri != old_select))
- bgp_info_reap (rn, ri);
-
- continue;
- }
- if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)
- && (! CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)))
- {
- bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
- continue;
- }
- bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
- bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED);
- if (bgp_info_cmp (bgp, ri, new_select, &paths_eq))
- {
- if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
- bgp_mp_dmed_deselect (new_select);
- new_select = ri;
- if (do_mpath && !paths_eq)
- {
- bgp_mp_list_clear (&mp_list);
- bgp_mp_list_add (&mp_list, ri);
- }
- }
- else if (do_mpath && bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
- bgp_mp_dmed_deselect (ri);
- if (do_mpath && paths_eq)
- bgp_mp_list_add (&mp_list, ri);
- }
-
- if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
- bgp_info_mpath_update (rn, new_select, old_select, &mp_list, mpath_cfg);
- bgp_info_mpath_aggregate_update (new_select, old_select);
- bgp_mp_list_clear (&mp_list);
- result->old = old_select;
- result->new = new_select;
- return;
- }
- static int
- bgp_process_announce_selected (struct peer *peer, struct bgp_info *selected,
- struct bgp_node *rn, afi_t afi, safi_t safi)
- {
- struct prefix *p;
- struct attr attr;
- struct attr_extra extra;
- p = &rn->p;
- /* Announce route to Established peer. */
- if (peer->status != Established)
- return 0;
- /* Address family configuration check. */
- if (! peer->afc_nego[afi][safi])
- return 0;
- /* First update is deferred until ORF or ROUTE-REFRESH is received */
- if (CHECK_FLAG (peer->af_sflags[afi][safi],
- PEER_STATUS_ORF_WAIT_REFRESH))
- return 0;
- /* It's initialized in bgp_announce_[check|check_rsclient]() */
- attr.extra = &extra;
- switch (bgp_node_table (rn)->type)
- {
- case BGP_TABLE_MAIN:
- /* Announcement to peer->conf. If the route is filtered,
- withdraw it. */
- if (selected && bgp_announce_check (selected, peer, p, &attr, afi, safi))
- bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected);
- else
- bgp_adj_out_unset (rn, peer, p, afi, safi);
- break;
- case BGP_TABLE_RSCLIENT:
- /* Announcement to peer->conf. If the route is filtered,
- withdraw it. */
- if (selected &&
- bgp_announce_check_rsclient (selected, peer, p, &attr, afi, safi))
- bgp_adj_out_set (rn, peer, p, &attr, afi, safi, selected);
- else
- bgp_adj_out_unset (rn, peer, p, afi, safi);
- break;
- }
- return 0;
- }
- struct bgp_process_queue
- {
- struct bgp *bgp;
- struct bgp_node *rn;
- afi_t afi;
- safi_t safi;
- };
- static wq_item_status
- bgp_process_rsclient (struct work_queue *wq, void *data)
- {
- struct bgp_process_queue *pq = data;
- struct bgp *bgp = pq->bgp;
- struct bgp_node *rn = pq->rn;
- afi_t afi = pq->afi;
- safi_t safi = pq->safi;
- struct bgp_info *new_select;
- struct bgp_info *old_select;
- struct bgp_info_pair old_and_new;
- struct listnode *node, *nnode;
- struct peer *rsclient = bgp_node_table (rn)->owner;
-
- /* Best path selection. */
- bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
- new_select = old_and_new.new;
- old_select = old_and_new.old;
- if (CHECK_FLAG (rsclient->sflags, PEER_STATUS_GROUP))
- {
- if (rsclient->group)
- for (ALL_LIST_ELEMENTS (rsclient->group->peer, node, nnode, rsclient))
- {
- /* Nothing to do. */
- if (old_select && old_select == new_select)
- if (!CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
- continue;
- if (old_select)
- bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
- if (new_select)
- {
- bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
- bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
- UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
- }
- bgp_process_announce_selected (rsclient, new_select, rn,
- afi, safi);
- }
- }
- else
- {
- if (old_select)
- bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
- if (new_select)
- {
- bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
- bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
- UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
- }
- bgp_process_announce_selected (rsclient, new_select, rn, afi, safi);
- }
- if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED))
- bgp_info_reap (rn, old_select);
-
- UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
- return WQ_SUCCESS;
- }
- static wq_item_status
- bgp_process_main (struct work_queue *wq, void *data)
- {
- struct bgp_process_queue *pq = data;
- struct bgp *bgp = pq->bgp;
- struct bgp_node *rn = pq->rn;
- afi_t afi = pq->afi;
- safi_t safi = pq->safi;
- struct prefix *p = &rn->p;
- struct bgp_info *new_select;
- struct bgp_info *old_select;
- struct bgp_info_pair old_and_new;
- struct listnode *node, *nnode;
- struct peer *peer;
-
- /* Best path selection. */
- bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
- old_select = old_and_new.old;
- new_select = old_and_new.new;
- /* Nothing to do. */
- if (old_select && old_select == new_select)
- {
- if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
- {
- if (CHECK_FLAG (old_select->flags, BGP_INFO_IGP_CHANGED) ||
- CHECK_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG))
- bgp_zebra_announce (p, old_select, bgp, safi);
-
- UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
- UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
- return WQ_SUCCESS;
- }
- }
- if (old_select)
- bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
- if (new_select)
- {
- bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
- bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
- UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
- }
- /* Check each BGP peer. */
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- {
- bgp_process_announce_selected (peer, new_select, rn, afi, safi);
- }
- /* FIB update. */
- if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && (! bgp->name &&
- ! bgp_option_check (BGP_OPT_NO_FIB)))
- {
- if (new_select
- && new_select->type == ZEBRA_ROUTE_BGP
- && new_select->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_announce (p, new_select, bgp, safi);
- else
- {
- /* Withdraw the route from the kernel. */
- if (old_select
- && old_select->type == ZEBRA_ROUTE_BGP
- && old_select->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_withdraw (p, old_select, safi);
- }
- }
-
- /* Reap old select bgp_info, it it has been removed */
- if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED))
- bgp_info_reap (rn, old_select);
-
- UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
- return WQ_SUCCESS;
- }
- static void
- bgp_processq_del (struct work_queue *wq, void *data)
- {
- struct bgp_process_queue *pq = data;
- struct bgp_table *table = bgp_node_table (pq->rn);
-
- bgp_unlock (pq->bgp);
- bgp_unlock_node (pq->rn);
- bgp_table_unlock (table);
- XFREE (MTYPE_BGP_PROCESS_QUEUE, pq);
- }
- static void
- bgp_process_queue_init (void)
- {
- bm->process_main_queue
- = work_queue_new (bm->master, "process_main_queue");
- bm->process_rsclient_queue
- = work_queue_new (bm->master, "process_rsclient_queue");
-
- if ( !(bm->process_main_queue && bm->process_rsclient_queue) )
- {
- zlog_err ("%s: Failed to allocate work queue", __func__);
- exit (1);
- }
-
- bm->process_main_queue->spec.workfunc = &bgp_process_main;
- bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
- bm->process_main_queue->spec.max_retries = 0;
- bm->process_main_queue->spec.hold = 50;
-
- memcpy (bm->process_rsclient_queue, bm->process_main_queue,
- sizeof (struct work_queue *));
- bm->process_rsclient_queue->spec.workfunc = &bgp_process_rsclient;
- }
- void
- bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
- {
- struct bgp_process_queue *pqnode;
-
- /* already scheduled for processing? */
- if (CHECK_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED))
- return;
-
- if ( (bm->process_main_queue == NULL) ||
- (bm->process_rsclient_queue == NULL) )
- bgp_process_queue_init ();
-
- pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE,
- sizeof (struct bgp_process_queue));
- if (!pqnode)
- return;
- /* all unlocked in bgp_processq_del */
- bgp_table_lock (bgp_node_table (rn));
- pqnode->rn = bgp_lock_node (rn);
- pqnode->bgp = bgp;
- bgp_lock (bgp);
- pqnode->afi = afi;
- pqnode->safi = safi;
-
- switch (bgp_node_table (rn)->type)
- {
- case BGP_TABLE_MAIN:
- work_queue_add (bm->process_main_queue, pqnode);
- break;
- case BGP_TABLE_RSCLIENT:
- work_queue_add (bm->process_rsclient_queue, pqnode);
- break;
- }
-
- return;
- }
- static int
- bgp_maximum_prefix_restart_timer (struct thread *thread)
- {
- struct peer *peer;
- peer = THREAD_ARG (thread);
- peer->t_pmax_restart = NULL;
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s Maximum-prefix restart timer expired, restore peering",
- peer->host);
- peer_clear (peer);
- return 0;
- }
- int
- bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
- safi_t safi, int always)
- {
- if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
- return 0;
- if (peer->pcount[afi][safi] > peer->pmax[afi][safi])
- {
- if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT)
- && ! always)
- return 0;
- zlog (peer->log, LOG_INFO,
- "%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
- "limit %ld", afi_safi_print (afi, safi), peer->host,
- peer->pcount[afi][safi], peer->pmax[afi][safi]);
- SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
- if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
- return 0;
- {
- u_int8_t ndata[7];
- if (safi == SAFI_MPLS_VPN)
- safi = SAFI_MPLS_LABELED_VPN;
-
- ndata[0] = (afi >> 8);
- ndata[1] = afi;
- ndata[2] = safi;
- ndata[3] = (peer->pmax[afi][safi] >> 24);
- ndata[4] = (peer->pmax[afi][safi] >> 16);
- ndata[5] = (peer->pmax[afi][safi] >> 8);
- ndata[6] = (peer->pmax[afi][safi]);
- SET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
- bgp_notify_send_with_data (peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_MAX_PREFIX, ndata, 7);
- }
- /* restart timer start */
- if (peer->pmax_restart[afi][safi])
- {
- peer->v_pmax_restart = peer->pmax_restart[afi][safi] * 60;
- if (BGP_DEBUG (events, EVENTS))
- zlog_debug ("%s Maximum-prefix restart timer started for %d secs",
- peer->host, peer->v_pmax_restart);
- BGP_TIMER_ON (peer->t_pmax_restart, bgp_maximum_prefix_restart_timer,
- peer->v_pmax_restart);
- }
- return 1;
- }
- else
- UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
- if (peer->pcount[afi][safi] > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100))
- {
- if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD)
- && ! always)
- return 0;
- zlog (peer->log, LOG_INFO,
- "%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
- afi_safi_print (afi, safi), peer->host, peer->pcount[afi][safi],
- peer->pmax[afi][safi]);
- SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);
- }
- else
- UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD);
- return 0;
- }
- /* Unconditionally remove the route from the RIB, without taking
- * damping into consideration (eg, because the session went down)
- */
- static void
- bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
- afi_t afi, safi_t safi)
- {
- bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
-
- if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
- bgp_info_delete (rn, ri); /* keep historical info */
-
- bgp_process (peer->bgp, rn, afi, safi);
- }
- static void
- bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
- afi_t afi, safi_t safi)
- {
- int status = BGP_DAMP_NONE;
- /* apply dampening, if result is suppressed, we'll be retaining
- * the bgp_info in the RIB for historical reference.
- */
- if (CHECK_FLAG (peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP)
- if ( (status = bgp_damp_withdraw (ri, rn, afi, safi, 0))
- == BGP_DAMP_SUPPRESSED)
- {
- bgp_aggregate_decrement (peer->bgp, &rn->p, ri, afi, safi);
- return;
- }
-
- bgp_rib_remove (rn, ri, peer, afi, safi);
- }
- static void
- bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
- struct attr *attr, struct peer *peer, struct prefix *p, int type,
- int sub_type, struct prefix_rd *prd, u_char *tag)
- {
- struct bgp_node *rn;
- struct bgp *bgp;
- struct attr new_attr;
- struct attr_extra new_extra;
- struct attr *attr_new;
- struct attr *attr_new2;
- struct bgp_info *ri;
- struct bgp_info *new;
- const char *reason;
- char buf[SU_ADDRSTRLEN];
- /* Do not insert announces from a rsclient into its own 'bgp_table'. */
- if (peer == rsclient)
- return;
- bgp = peer->bgp;
- rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, prd);
- /* Check previously received route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
- break;
- /* AS path loop check. */
- if (aspath_loop_check (attr->aspath, rsclient->as) > peer->allowas_in[afi][safi])
- {
- reason = "as-path contains our own AS;";
- goto filtered;
- }
- /* Route reflector originator ID check. */
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)
- && IPV4_ADDR_SAME (&rsclient->remote_id, &attr->extra->originator_id))
- {
- reason = "originator is us;";
- goto filtered;
- }
-
- new_attr.extra = &new_extra;
- bgp_attr_dup (&new_attr, attr);
- /* Apply export policy. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT) &&
- bgp_export_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
- {
- reason = "export-policy;";
- goto filtered;
- }
- attr_new2 = bgp_attr_intern (&new_attr);
-
- /* Apply import policy. */
- if (bgp_import_modifier (rsclient, peer, p, &new_attr, afi, safi) == RMAP_DENY)
- {
- bgp_attr_unintern (&attr_new2);
- reason = "import-policy;";
- goto filtered;
- }
- attr_new = bgp_attr_intern (&new_attr);
- bgp_attr_unintern (&attr_new2);
- /* IPv4 unicast next hop check. */
- if ((afi == AFI_IP) && ((safi == SAFI_UNICAST) || safi == SAFI_MULTICAST))
- {
- /* Next hop must not be 0.0.0.0 nor Class D/E address. */
- if (new_attr.nexthop.s_addr == 0
- || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr)))
- {
- bgp_attr_unintern (&attr_new);
- reason = "martian next-hop;";
- goto filtered;
- }
- }
- /* If the update is implicit withdraw. */
- if (ri)
- {
- ri->uptime = bgp_clock ();
- /* Same attribute comes in. */
- if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)
- && attrhash_cmp (ri->attr, attr_new))
- {
- bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd %s/%d for RS-client %s...duplicate ignored",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
- bgp_unlock_node (rn);
- bgp_attr_unintern (&attr_new);
- return;
- }
- /* Withdraw/Announce before we fully processed the withdraw */
- if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
- bgp_info_restore (rn, ri);
-
- /* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
- /* The attribute is changed. */
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- /* Update to new attribute. */
- bgp_attr_unintern (&ri->attr);
- ri->attr = attr_new;
- /* Update MPLS tag. */
- if (safi == SAFI_MPLS_VPN)
- memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
- bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- bgp_unlock_node (rn);
- return;
- }
- /* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- {
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d for RS-client %s",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
- }
- /* Make new BGP info. */
- new = bgp_info_new ();
- new->type = type;
- new->sub_type = sub_type;
- new->peer = peer;
- new->attr = attr_new;
- new->uptime = bgp_clock ();
- /* Update MPLS tag. */
- if (safi == SAFI_MPLS_VPN)
- memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
- bgp_info_set_flag (rn, new, BGP_INFO_VALID);
- /* Register new BGP information. */
- bgp_info_add (rn, new);
-
- /* route_node_get lock */
- bgp_unlock_node (rn);
-
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- return;
- filtered:
- /* This BGP update is filtered. Log the reason then update BGP entry. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd UPDATE about %s/%d -- DENIED for RS-client %s due to: %s",
- peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host, reason);
- if (ri)
- bgp_rib_remove (rn, ri, peer, afi, safi);
- bgp_unlock_node (rn);
- return;
- }
- static void
- bgp_withdraw_rsclient (struct peer *rsclient, afi_t afi, safi_t safi,
- struct peer *peer, struct prefix *p, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- char buf[SU_ADDRSTRLEN];
- if (rsclient == peer)
- return;
- rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, prd);
- /* Lookup withdrawn route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
- break;
- /* Withdraw specified route from routing table. */
- if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
- bgp_rib_withdraw (rn, ri, peer, afi, safi);
- else if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s Can't find the route %s/%d", peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- /* Unlock bgp_node_get() lock. */
- bgp_unlock_node (rn);
- }
- static int
- bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag, int soft_reconfig)
- {
- int ret;
- int aspath_loop_count = 0;
- struct bgp_node *rn;
- struct bgp *bgp;
- struct attr new_attr;
- struct attr_extra new_extra;
- struct attr *attr_new;
- struct bgp_info *ri;
- struct bgp_info *new;
- const char *reason;
- char buf[SU_ADDRSTRLEN];
- bgp = peer->bgp;
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
-
- /* When peer's soft reconfiguration enabled. Record input packet in
- Adj-RIBs-In. */
- if (! soft_reconfig && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
- && peer != bgp->peer_self)
- bgp_adj_in_set (rn, peer, attr);
- /* Check previously received route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
- break;
- /* AS path local-as loop check. */
- if (peer->change_local_as)
- {
- if (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
- aspath_loop_count = 1;
- if (aspath_loop_check (attr->aspath, peer->change_local_as) > aspath_loop_count)
- {
- reason = "as-path contains our own AS;";
- goto filtered;
- }
- }
- /* AS path loop check. */
- if (aspath_loop_check (attr->aspath, bgp->as) > peer->allowas_in[afi][safi]
- || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
- && aspath_loop_check(attr->aspath, bgp->confed_id)
- > peer->allowas_in[afi][safi]))
- {
- reason = "as-path contains our own AS;";
- goto filtered;
- }
- /* Route reflector originator ID check. */
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)
- && IPV4_ADDR_SAME (&bgp->router_id, &attr->extra->originator_id))
- {
- reason = "originator is us;";
- goto filtered;
- }
- /* Route reflector cluster ID check. */
- if (bgp_cluster_filter (peer, attr))
- {
- reason = "reflected from the same cluster;";
- goto filtered;
- }
- /* Apply incoming filter. */
- if (bgp_input_filter (peer, p, attr, afi, safi) == FILTER_DENY)
- {
- reason = "filter;";
- goto filtered;
- }
- new_attr.extra = &new_extra;
- bgp_attr_dup (&new_attr, attr);
- /* Apply incoming route-map. */
- if (bgp_input_modifier (peer, p, &new_attr, afi, safi) == RMAP_DENY)
- {
- reason = "route-map;";
- goto filtered;
- }
- /* IPv4 unicast next hop check. */
- if (afi == AFI_IP && safi == SAFI_UNICAST)
- {
- /* If the peer is EBGP and nexthop is not on connected route,
- discard it. */
- if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
- && ! bgp_nexthop_onlink (afi, &new_attr)
- && ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
- {
- reason = "non-connected next-hop;";
- goto filtered;
- }
- /* Next hop must not be 0.0.0.0 nor Class D/E address. Next hop
- must not be my own address. */
- if (new_attr.nexthop.s_addr == 0
- || IPV4_CLASS_DE (ntohl (new_attr.nexthop.s_addr))
- || bgp_nexthop_self (&new_attr))
- {
- reason = "martian next-hop;";
- goto filtered;
- }
- }
- attr_new = bgp_attr_intern (&new_attr);
- /* If the update is implicit withdraw. */
- if (ri)
- {
- ri->uptime = bgp_clock ();
- /* Same attribute comes in. */
- if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
- && attrhash_cmp (ri->attr, attr_new))
- {
- bgp_info_unset_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP
- && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
- {
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED)
- {
- bgp_aggregate_increment (bgp, p, ri, afi, safi);
- bgp_process (bgp, rn, afi, safi);
- }
- }
- else /* Duplicate - odd */
- {
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd %s/%d...duplicate ignored",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- /* graceful restart STALE flag unset. */
- if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
- {
- bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
- bgp_process (bgp, rn, afi, safi);
- }
- }
- bgp_unlock_node (rn);
- bgp_attr_unintern (&attr_new);
- return 0;
- }
- /* Withdraw/Announce before we fully processed the withdraw */
- if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
- {
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d, flapped quicker than processing",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- bgp_info_restore (rn, ri);
- }
- /* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- /* graceful restart STALE flag unset. */
- if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
- bgp_info_unset_flag (rn, ri, BGP_INFO_STALE);
- /* The attribute is changed. */
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
-
- /* implicit withdraw, decrement aggregate and pcount here.
- * only if update is accepted, they'll increment below.
- */
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
-
- /* Update bgp route dampening information. */
- if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP)
- {
- /* This is implicit withdraw so we should update dampening
- information. */
- if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
- bgp_damp_withdraw (ri, rn, afi, safi, 1);
- }
-
- /* Update to new attribute. */
- bgp_attr_unintern (&ri->attr);
- ri->attr = attr_new;
- /* Update MPLS tag. */
- if (safi == SAFI_MPLS_VPN)
- memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
- /* Update bgp route dampening information. */
- if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP)
- {
- /* Now we do normal update dampening. */
- ret = bgp_damp_update (ri, rn, afi, safi);
- if (ret == BGP_DAMP_SUPPRESSED)
- {
- bgp_unlock_node (rn);
- return 0;
- }
- }
- /* Nexthop reachability check. */
- if ((afi == AFI_IP || afi == AFI_IP6)
- && safi == SAFI_UNICAST
- && (peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED
- || (peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
- || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
- {
- if (bgp_nexthop_lookup (afi, peer, ri, NULL, NULL))
- bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
- else
- bgp_info_unset_flag (rn, ri, BGP_INFO_VALID);
- }
- else
- bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
- /* Process change. */
- bgp_aggregate_increment (bgp, p, ri, afi, safi);
- bgp_process (bgp, rn, afi, safi);
- bgp_unlock_node (rn);
- return 0;
- }
- /* Received Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- {
- zlog (peer->log, LOG_DEBUG, "%s rcvd %s/%d",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- }
- /* Make new BGP info. */
- new = bgp_info_new ();
- new->type = type;
- new->sub_type = sub_type;
- new->peer = peer;
- new->attr = attr_new;
- new->uptime = bgp_clock ();
- /* Update MPLS tag. */
- if (safi == SAFI_MPLS_VPN)
- memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
- /* Nexthop reachability check. */
- if ((afi == AFI_IP || afi == AFI_IP6)
- && safi == SAFI_UNICAST
- && (peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED
- || (peer->sort == BGP_PEER_EBGP && peer->ttl != 1)
- || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)))
- {
- if (bgp_nexthop_lookup (afi, peer, new, NULL, NULL))
- bgp_info_set_flag (rn, new, BGP_INFO_VALID);
- else
- bgp_info_unset_flag (rn, new, BGP_INFO_VALID);
- }
- else
- bgp_info_set_flag (rn, new, BGP_INFO_VALID);
- /* Increment prefix */
- bgp_aggregate_increment (bgp, p, new, afi, safi);
-
- /* Register new BGP information. */
- bgp_info_add (rn, new);
-
- /* route_node_get lock */
- bgp_unlock_node (rn);
- /* If maximum prefix count is configured and current prefix
- count exeed it. */
- if (bgp_maximum_prefix_overflow (peer, afi, safi, 0))
- return -1;
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- return 0;
- /* This BGP update is filtered. Log the reason then update BGP
- entry. */
- filtered:
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s rcvd UPDATE about %s/%d -- DENIED due to: %s",
- peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, reason);
- if (ri)
- bgp_rib_remove (rn, ri, peer, afi, safi);
- bgp_unlock_node (rn);
- return 0;
- }
- int
- bgp_update (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag, int soft_reconfig)
- {
- struct peer *rsclient;
- struct listnode *node, *nnode;
- struct bgp *bgp;
- int ret;
- ret = bgp_update_main (peer, p, attr, afi, safi, type, sub_type, prd, tag,
- soft_reconfig);
- bgp = peer->bgp;
- /* Process the update for each RS-client. */
- for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
- {
- if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_update_rsclient (rsclient, afi, safi, attr, peer, p, type,
- sub_type, prd, tag);
- }
- return ret;
- }
- int
- bgp_withdraw (struct peer *peer, struct prefix *p, struct attr *attr,
- afi_t afi, safi_t safi, int type, int sub_type,
- struct prefix_rd *prd, u_char *tag)
- {
- struct bgp *bgp;
- char buf[SU_ADDRSTRLEN];
- struct bgp_node *rn;
- struct bgp_info *ri;
- struct peer *rsclient;
- struct listnode *node, *nnode;
- bgp = peer->bgp;
- /* Process the withdraw for each RS-client. */
- for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
- {
- if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_withdraw_rsclient (rsclient, afi, safi, peer, p, type, sub_type, prd, tag);
- }
- /* Logging. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG, "%s rcvd UPDATE about %s/%d -- withdrawn",
- peer->host,
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- /* Lookup node. */
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
- /* If peer is soft reconfiguration enabled. Record input packet for
- further calculation. */
- if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
- && peer != bgp->peer_self)
- bgp_adj_in_unset (rn, peer);
- /* Lookup withdrawn route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer && ri->type == type && ri->sub_type == sub_type)
- break;
- /* Withdraw specified route from routing table. */
- if (ri && ! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
- bgp_rib_withdraw (rn, ri, peer, afi, safi);
- else if (BGP_DEBUG (update, UPDATE_IN))
- zlog (peer->log, LOG_DEBUG,
- "%s Can't find the route %s/%d", peer->host,
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
- /* Unlock bgp_node_get() lock. */
- bgp_unlock_node (rn);
- return 0;
- }
- void
- bgp_default_originate (struct peer *peer, afi_t afi, safi_t safi, int withdraw)
- {
- struct bgp *bgp;
- struct attr attr;
- struct aspath *aspath;
- struct prefix p;
- struct bgp_info binfo;
- struct peer *from;
- int ret = RMAP_DENYMATCH;
-
- if (!(afi == AFI_IP || afi == AFI_IP6))
- return;
-
- bgp = peer->bgp;
- from = bgp->peer_self;
-
- bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
- aspath = attr.aspath;
- attr.local_pref = bgp->default_local_pref;
- memcpy (&attr.nexthop, &peer->nexthop.v4, IPV4_MAX_BYTELEN);
- if (afi == AFI_IP)
- str2prefix ("0.0.0.0/0", &p);
- #ifdef HAVE_IPV6
- else if (afi == AFI_IP6)
- {
- struct attr_extra *ae = attr.extra;
- str2prefix ("::/0", &p);
- /* IPv6 global nexthop must be included. */
- memcpy (&ae->mp_nexthop_global, &peer->nexthop.v6_global,
- IPV6_MAX_BYTELEN);
- ae->mp_nexthop_len = 16;
-
- /* If the peer is on shared nextwork and we have link-local
- nexthop set it. */
- if (peer->shared_network
- && !IN6_IS_ADDR_UNSPECIFIED (&peer->nexthop.v6_local))
- {
- memcpy (&ae->mp_nexthop_local, &peer->nexthop.v6_local,
- IPV6_MAX_BYTELEN);
- ae->mp_nexthop_len = 32;
- }
- }
- #endif /* HAVE_IPV6 */
- if (peer->default_rmap[afi][safi].name)
- {
- binfo.peer = bgp->peer_self;
- binfo.attr = &attr;
- SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
- ret = route_map_apply (peer->default_rmap[afi][safi].map, &p,
- RMAP_BGP, &binfo);
- bgp->peer_self->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- bgp_attr_flush (&attr);
- withdraw = 1;
- }
- }
- if (withdraw)
- {
- if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE))
- bgp_default_withdraw_send (peer, afi, safi);
- UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE);
- }
- else
- {
- SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_DEFAULT_ORIGINATE);
- bgp_default_update_send (peer, &attr, afi, safi, from);
- }
-
- bgp_attr_extra_free (&attr);
- aspath_unintern (&aspath);
- }
- static void
- bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_table *table, int rsclient)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- struct attr attr;
- struct attr_extra extra;
- if (! table)
- table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi];
- if (safi != SAFI_MPLS_VPN
- && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
- bgp_default_originate (peer, afi, safi, 0);
- /* It's initialized in bgp_announce_[check|check_rsclient]() */
- attr.extra = &extra;
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next(rn))
- for (ri = rn->info; ri; ri = ri->next)
- if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) && ri->peer != peer)
- {
- if ( (rsclient) ?
- (bgp_announce_check_rsclient (ri, peer, &rn->p, &attr, afi, safi))
- : (bgp_announce_check (ri, peer, &rn->p, &attr, afi, safi)))
- bgp_adj_out_set (rn, peer, &rn->p, &attr, afi, safi, ri);
- else
- bgp_adj_out_unset (rn, peer, &rn->p, afi, safi);
- }
- }
- void
- bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_table *table;
- if (peer->status != Established)
- return;
- if (! peer->afc_nego[afi][safi])
- return;
- /* First update is deferred until ORF or ROUTE-REFRESH is received */
- if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
- return;
- if (safi != SAFI_MPLS_VPN)
- bgp_announce_table (peer, afi, safi, NULL, 0);
- else
- for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
- rn = bgp_route_next(rn))
- if ((table = (rn->info)) != NULL)
- bgp_announce_table (peer, afi, safi, table, 0);
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_announce_table (peer, afi, safi, NULL, 1);
- }
- void
- bgp_announce_route_all (struct peer *peer)
- {
- afi_t afi;
- safi_t safi;
-
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- bgp_announce_route (peer, afi, safi);
- }
- static void
- bgp_soft_reconfig_table_rsclient (struct peer *rsclient, afi_t afi,
- safi_t safi, struct bgp_table *table, struct prefix_rd *prd)
- {
- struct bgp_node *rn;
- struct bgp_adj_in *ain;
- if (! table)
- table = rsclient->bgp->rib[afi][safi];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- for (ain = rn->adj_in; ain; ain = ain->next)
- {
- struct bgp_info *ri = rn->info;
- bgp_update_rsclient (rsclient, afi, safi, ain->attr, ain->peer,
- &rn->p, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
- (bgp_info_extra_get (ri))->tag);
- }
- }
- void
- bgp_soft_reconfig_rsclient (struct peer *rsclient, afi_t afi, safi_t safi)
- {
- struct bgp_table *table;
- struct bgp_node *rn;
-
- if (safi != SAFI_MPLS_VPN)
- bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, NULL, NULL);
- else
- for (rn = bgp_table_top (rsclient->bgp->rib[afi][safi]); rn;
- rn = bgp_route_next (rn))
- if ((table = rn->info) != NULL)
- {
- struct prefix_rd prd;
- prd.family = AF_UNSPEC;
- prd.prefixlen = 64;
- memcpy(&prd.val, rn->p.u.val, 8);
- bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, table, &prd);
- }
- }
- static void
- bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_table *table, struct prefix_rd *prd)
- {
- int ret;
- struct bgp_node *rn;
- struct bgp_adj_in *ain;
- if (! table)
- table = peer->bgp->rib[afi][safi];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- for (ain = rn->adj_in; ain; ain = ain->next)
- {
- if (ain->peer == peer)
- {
- struct bgp_info *ri = rn->info;
- ret = bgp_update (peer, &rn->p, ain->attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- prd, (bgp_info_extra_get (ri))->tag, 1);
- if (ret < 0)
- {
- bgp_unlock_node (rn);
- return;
- }
- continue;
- }
- }
- }
- void
- bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_table *table;
- if (peer->status != Established)
- return;
- if (safi != SAFI_MPLS_VPN)
- bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL);
- else
- for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
- rn = bgp_route_next (rn))
- if ((table = rn->info) != NULL)
- {
- struct prefix_rd prd;
- prd.family = AF_UNSPEC;
- prd.prefixlen = 64;
- memcpy(&prd.val, rn->p.u.val, 8);
- bgp_soft_reconfig_table (peer, afi, safi, table, &prd);
- }
- }
- struct bgp_clear_node_queue
- {
- struct bgp_node *rn;
- enum bgp_clear_route_type purpose;
- };
- static wq_item_status
- bgp_clear_route_node (struct work_queue *wq, void *data)
- {
- struct bgp_clear_node_queue *cnq = data;
- struct bgp_node *rn = cnq->rn;
- struct peer *peer = wq->spec.data;
- struct bgp_info *ri;
- afi_t afi = bgp_node_table (rn)->afi;
- safi_t safi = bgp_node_table (rn)->safi;
-
- assert (rn && peer);
-
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
- {
- /* graceful restart STALE flag set. */
- if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT)
- && peer->nsf[afi][safi]
- && ! CHECK_FLAG (ri->flags, BGP_INFO_STALE)
- && ! CHECK_FLAG (ri->flags, BGP_INFO_UNUSEABLE))
- bgp_info_set_flag (rn, ri, BGP_INFO_STALE);
- else
- bgp_rib_remove (rn, ri, peer, afi, safi);
- break;
- }
- return WQ_SUCCESS;
- }
- static void
- bgp_clear_node_queue_del (struct work_queue *wq, void *data)
- {
- struct bgp_clear_node_queue *cnq = data;
- struct bgp_node *rn = cnq->rn;
- struct bgp_table *table = bgp_node_table (rn);
-
- bgp_unlock_node (rn);
- bgp_table_unlock (table);
- XFREE (MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
- }
- static void
- bgp_clear_node_complete (struct work_queue *wq)
- {
- struct peer *peer = wq->spec.data;
-
- /* Tickle FSM to start moving again */
- BGP_EVENT_ADD (peer, Clearing_Completed);
- peer_unlock (peer); /* bgp_clear_route */
- }
- static void
- bgp_clear_node_queue_init (struct peer *peer)
- {
- char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
-
- snprintf (wname, sizeof(wname), "clear %s", peer->host);
- #undef CLEAR_QUEUE_NAME_LEN
- if ( (peer->clear_node_queue = work_queue_new (bm->master, wname)) == NULL)
- {
- zlog_err ("%s: Failed to allocate work queue", __func__);
- exit (1);
- }
- peer->clear_node_queue->spec.hold = 10;
- peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
- peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
- peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
- peer->clear_node_queue->spec.max_retries = 0;
-
- /* we only 'lock' this peer reference when the queue is actually active */
- peer->clear_node_queue->spec.data = peer;
- }
- static void
- bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
- struct bgp_table *table, struct peer *rsclient,
- enum bgp_clear_route_type purpose)
- {
- struct bgp_node *rn;
-
-
- if (! table)
- table = (rsclient) ? rsclient->rib[afi][safi] : peer->bgp->rib[afi][safi];
-
- /* If still no table => afi/safi isn't configured at all or smth. */
- if (! table)
- return;
-
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- {
- struct bgp_info *ri;
- struct bgp_adj_in *ain;
- struct bgp_adj_out *aout;
-
- if (rn->info == NULL)
- continue;
- /* XXX:TODO: This is suboptimal, every non-empty route_node is
- * queued for every clearing peer, regardless of whether it is
- * relevant to the peer at hand.
- *
- * Overview: There are 3 different indices which need to be
- * scrubbed, potentially, when a peer is removed:
- *
- * 1 peer's routes visible via the RIB (ie accepted routes)
- * 2 peer's routes visible by the (optional) peer's adj-in index
- * 3 other routes visible by the peer's adj-out index
- *
- * 3 there is no hurry in scrubbing, once the struct peer is
- * removed from bgp->peer, we could just GC such deleted peer's
- * adj-outs at our leisure.
- *
- * 1 and 2 must be 'scrubbed' in some way, at least made
- * invisible via RIB index before peer session is allowed to be
- * brought back up. So one needs to know when such a 'search' is
- * complete.
- *
- * Ideally:
- *
- * - there'd be a single global queue or a single RIB walker
- * - rather than tracking which route_nodes still need to be
- * examined on a peer basis, we'd track which peers still
- * aren't cleared
- *
- * Given that our per-peer prefix-counts now should be reliable,
- * this may actually be achievable. It doesn't seem to be a huge
- * problem at this time,
- */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
- {
- struct bgp_clear_node_queue *cnq;
- /* both unlocked in bgp_clear_node_queue_del */
- bgp_table_lock (bgp_node_table (rn));
- bgp_lock_node (rn);
- cnq = XCALLOC (MTYPE_BGP_CLEAR_NODE_QUEUE,
- sizeof (struct bgp_clear_node_queue));
- cnq->rn = rn;
- cnq->purpose = purpose;
- work_queue_add (peer->clear_node_queue, cnq);
- break;
- }
- for (ain = rn->adj_in; ain; ain = ain->next)
- if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
- {
- bgp_adj_in_remove (rn, ain);
- bgp_unlock_node (rn);
- break;
- }
- for (aout = rn->adj_out; aout; aout = aout->next)
- if (aout->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
- {
- bgp_adj_out_remove (rn, aout, peer, afi, safi);
- bgp_unlock_node (rn);
- break;
- }
- }
- return;
- }
- void
- bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi,
- enum bgp_clear_route_type purpose)
- {
- struct bgp_node *rn;
- struct bgp_table *table;
- struct peer *rsclient;
- struct listnode *node, *nnode;
- if (peer->clear_node_queue == NULL)
- bgp_clear_node_queue_init (peer);
-
- /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
- * Idle until it receives a Clearing_Completed event. This protects
- * against peers which flap faster than we can we clear, which could
- * lead to:
- *
- * a) race with routes from the new session being installed before
- * clear_route_node visits the node (to delete the route of that
- * peer)
- * b) resource exhaustion, clear_route_node likely leads to an entry
- * on the process_main queue. Fast-flapping could cause that queue
- * to grow and grow.
- */
- if (!peer->clear_node_queue->thread)
- peer_lock (peer); /* bgp_clear_node_complete */
- switch (purpose)
- {
- case BGP_CLEAR_ROUTE_NORMAL:
- if (safi != SAFI_MPLS_VPN)
- bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose);
- else
- for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn;
- rn = bgp_route_next (rn))
- if ((table = rn->info) != NULL)
- bgp_clear_route_table (peer, afi, safi, table, NULL, purpose);
- for (ALL_LIST_ELEMENTS (peer->bgp->rsclient, node, nnode, rsclient))
- if (CHECK_FLAG(rsclient->af_flags[afi][safi],
- PEER_FLAG_RSERVER_CLIENT))
- bgp_clear_route_table (peer, afi, safi, NULL, rsclient, purpose);
- break;
- case BGP_CLEAR_ROUTE_MY_RSCLIENT:
- bgp_clear_route_table (peer, afi, safi, NULL, peer, purpose);
- break;
- default:
- assert (0);
- break;
- }
-
- /* If no routes were cleared, nothing was added to workqueue, the
- * completion function won't be run by workqueue code - call it here.
- * XXX: Actually, this assumption doesn't hold, see
- * bgp_clear_route_table(), we queue all non-empty nodes.
- *
- * Additionally, there is a presumption in FSM that clearing is only
- * really needed if peer state is Established - peers in
- * pre-Established states shouldn't have any route-update state
- * associated with them (in or out).
- *
- * We still can get here in pre-Established though, through
- * peer_delete -> bgp_fsm_change_status, so this is a useful sanity
- * check to ensure the assumption above holds.
- *
- * At some future point, this check could be move to the top of the
- * function, and do a quick early-return when state is
- * pre-Established, avoiding above list and table scans. Once we're
- * sure it is safe..
- */
- if (!peer->clear_node_queue->thread)
- bgp_clear_node_complete (peer->clear_node_queue);
- }
-
- void
- bgp_clear_route_all (struct peer *peer)
- {
- afi_t afi;
- safi_t safi;
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
- }
- void
- bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi)
- {
- struct bgp_table *table;
- struct bgp_node *rn;
- struct bgp_adj_in *ain;
- table = peer->bgp->rib[afi][safi];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- for (ain = rn->adj_in; ain ; ain = ain->next)
- if (ain->peer == peer)
- {
- bgp_adj_in_remove (rn, ain);
- bgp_unlock_node (rn);
- break;
- }
- }
- void
- bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- struct bgp_table *table;
- table = peer->bgp->rib[afi][safi];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- {
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == peer)
- {
- if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
- bgp_rib_remove (rn, ri, peer, afi, safi);
- break;
- }
- }
- }
- /* Delete all kernel routes. */
- void
- bgp_cleanup_routes (void)
- {
- struct bgp *bgp;
- struct listnode *node, *nnode;
- struct bgp_node *rn;
- struct bgp_table *table;
- struct bgp_info *ri;
- for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
- {
- table = bgp->rib[AFI_IP][SAFI_UNICAST];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- for (ri = rn->info; ri; ri = ri->next)
- if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
- && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
- table = bgp->rib[AFI_IP6][SAFI_UNICAST];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- for (ri = rn->info; ri; ri = ri->next)
- if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
- && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_NORMAL)
- bgp_zebra_withdraw (&rn->p, ri,SAFI_UNICAST);
- }
- }
- void
- bgp_reset (void)
- {
- vty_reset ();
- bgp_zclient_reset ();
- access_list_reset ();
- prefix_list_reset ();
- }
- /* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
- value. */
- int
- bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
- {
- u_char *pnt;
- u_char *lim;
- struct prefix p;
- int psize;
- int ret;
- /* Check peer status. */
- if (peer->status != Established)
- return 0;
-
- pnt = packet->nlri;
- lim = pnt + packet->length;
- for (; pnt < lim; pnt += psize)
- {
- /* Clear prefix structure. */
- memset (&p, 0, sizeof (struct prefix));
- /* Fetch prefix length. */
- p.prefixlen = *pnt++;
- p.family = afi2family (packet->afi);
-
- /* Already checked in nlri_sanity_check(). We do double check
- here. */
- if ((packet->afi == AFI_IP && p.prefixlen > 32)
- || (packet->afi == AFI_IP6 && p.prefixlen > 128))
- return -1;
- /* Packet size overflow check. */
- psize = PSIZE (p.prefixlen);
- /* When packet overflow occur return immediately. */
- if (pnt + psize > lim)
- return -1;
- /* Fetch prefix from NLRI packet. */
- memcpy (&p.u.prefix, pnt, psize);
- /* Check address. */
- if (packet->afi == AFI_IP && packet->safi == SAFI_UNICAST)
- {
- if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
- {
- /*
- * From draft-ietf-idr-bgp4-22, Section 6.3:
- * If a BGP router receives an UPDATE message with a
- * semantically incorrect NLRI field, in which a prefix is
- * semantically incorrect (eg. an unexpected multicast IP
- * address), it should ignore the prefix.
- */
- zlog (peer->log, LOG_ERR,
- "IPv4 unicast NLRI is multicast address %s",
- inet_ntoa (p.u.prefix4));
- return -1;
- }
- }
- #ifdef HAVE_IPV6
- /* Check address. */
- if (packet->afi == AFI_IP6 && packet->safi == SAFI_UNICAST)
- {
- if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
- {
- char buf[BUFSIZ];
- zlog (peer->log, LOG_WARNING,
- "IPv6 link-local NLRI received %s ignore this NLRI",
- inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
- continue;
- }
- }
- #endif /* HAVE_IPV6 */
- /* Normal process. */
- if (attr)
- ret = bgp_update (peer, &p, attr, packet->afi, packet->safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL, 0);
- else
- ret = bgp_withdraw (peer, &p, attr, packet->afi, packet->safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, NULL);
- /* Address family configuration mismatch or maximum-prefix count
- overflow. */
- if (ret < 0)
- return -1;
- }
- /* Packet length consistency check. */
- if (pnt != lim)
- return -1;
- return 0;
- }
- /* NLRI encode syntax check routine. */
- int
- bgp_nlri_sanity_check (struct peer *peer, int afi, u_char *pnt,
- bgp_size_t length)
- {
- u_char *end;
- u_char prefixlen;
- int psize;
- end = pnt + length;
- /* RFC1771 6.3 The NLRI field in the UPDATE message is checked for
- syntactic validity. If the field is syntactically incorrect,
- then the Error Subcode is set to Invalid Network Field. */
- while (pnt < end)
- {
- prefixlen = *pnt++;
-
- /* Prefix length check. */
- if ((afi == AFI_IP && prefixlen > 32)
- || (afi == AFI_IP6 && prefixlen > 128))
- {
- plog_err (peer->log,
- "%s [Error] Update packet error (wrong prefix length %d)",
- peer->host, prefixlen);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NETWORK);
- return -1;
- }
- /* Packet size overflow check. */
- psize = PSIZE (prefixlen);
- if (pnt + psize > end)
- {
- plog_err (peer->log,
- "%s [Error] Update packet error"
- " (prefix data overflow prefix size is %d)",
- peer->host, psize);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NETWORK);
- return -1;
- }
- pnt += psize;
- }
- /* Packet length consistency check. */
- if (pnt != end)
- {
- plog_err (peer->log,
- "%s [Error] Update packet error"
- " (prefix length mismatch with total length)",
- peer->host);
- bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NETWORK);
- return -1;
- }
- return 0;
- }
- static struct bgp_static *
- bgp_static_new (void)
- {
- return XCALLOC (MTYPE_BGP_STATIC, sizeof (struct bgp_static));
- }
- static void
- bgp_static_free (struct bgp_static *bgp_static)
- {
- if (bgp_static->rmap.name)
- free (bgp_static->rmap.name);
- XFREE (MTYPE_BGP_STATIC, bgp_static);
- }
- static void
- bgp_static_withdraw_rsclient (struct bgp *bgp, struct peer *rsclient,
- struct prefix *p, afi_t afi, safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, NULL);
- /* Check selected route and self inserted route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self
- && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_STATIC)
- break;
- /* Withdraw static BGP route from routing table. */
- if (ri)
- {
- bgp_info_delete (rn, ri);
- bgp_process (bgp, rn, afi, safi);
- }
- /* Unlock bgp_node_lookup. */
- bgp_unlock_node (rn);
- }
- static void
- bgp_static_update_rsclient (struct peer *rsclient, struct prefix *p,
- struct bgp_static *bgp_static,
- afi_t afi, safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- struct bgp_info *new;
- struct bgp_info info;
- struct attr *attr_new;
- struct attr attr;
- struct attr new_attr;
- struct attr_extra new_extra;
- struct bgp *bgp;
- int ret;
- char buf[SU_ADDRSTRLEN];
- bgp = rsclient->bgp;
- assert (bgp_static);
- if (!bgp_static)
- return;
- rn = bgp_afi_node_get (rsclient->rib[afi][safi], afi, safi, p, NULL);
- bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
- attr.nexthop = bgp_static->igpnexthop;
- attr.med = bgp_static->igpmetric;
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
-
- if (bgp_static->atomic)
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
-
- /* Apply network route-map for export to this rsclient. */
- if (bgp_static->rmap.name)
- {
- struct attr attr_tmp = attr;
- info.peer = rsclient;
- info.attr = &attr_tmp;
-
- SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_EXPORT);
- SET_FLAG (rsclient->rmap_type, PEER_RMAP_TYPE_NETWORK);
- ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info);
- rsclient->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- /* Free uninterned attribute. */
- bgp_attr_flush (&attr_tmp);
- /* Unintern original. */
- aspath_unintern (&attr.aspath);
- bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
- bgp_attr_extra_free (&attr);
-
- return;
- }
- attr_new = bgp_attr_intern (&attr_tmp);
- }
- else
- attr_new = bgp_attr_intern (&attr);
- new_attr.extra = &new_extra;
- bgp_attr_dup(&new_attr, attr_new);
-
- SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
- if (bgp_import_modifier (rsclient, bgp->peer_self, p, &new_attr, afi, safi)
- == RMAP_DENY)
- {
- /* This BGP update is filtered. Log the reason then update BGP entry. */
- if (BGP_DEBUG (update, UPDATE_IN))
- zlog (rsclient->log, LOG_DEBUG,
- "Static UPDATE about %s/%d -- DENIED for RS-client %s due to: import-policy",
- inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen, rsclient->host);
- bgp->peer_self->rmap_type = 0;
- bgp_attr_unintern (&attr_new);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- bgp_static_withdraw_rsclient (bgp, rsclient, p, afi, safi);
-
- return;
- }
- bgp->peer_self->rmap_type = 0;
- bgp_attr_unintern (&attr_new);
- attr_new = bgp_attr_intern (&new_attr);
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_STATIC)
- break;
- if (ri)
- {
- if (attrhash_cmp (ri->attr, attr_new) &&
- !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
- {
- bgp_unlock_node (rn);
- bgp_attr_unintern (&attr_new);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- return;
- }
- else
- {
- /* The attribute is changed. */
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- /* Rewrite BGP route information. */
- if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
- bgp_info_restore(rn, ri);
- bgp_attr_unintern (&ri->attr);
- ri->attr = attr_new;
- ri->uptime = bgp_clock ();
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- bgp_unlock_node (rn);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- return;
- }
- }
-
- /* Make new BGP info. */
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_STATIC;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = attr_new;
- new->uptime = bgp_clock ();
- /* Register new BGP information. */
- bgp_info_add (rn, new);
-
- /* route_node_get lock */
- bgp_unlock_node (rn);
-
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- /* Unintern original. */
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- }
- static void
- bgp_static_update_main (struct bgp *bgp, struct prefix *p,
- struct bgp_static *bgp_static, afi_t afi, safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- struct bgp_info *new;
- struct bgp_info info;
- struct attr attr;
- struct attr *attr_new;
- int ret;
- assert (bgp_static);
- if (!bgp_static)
- return;
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL);
- bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
-
- attr.nexthop = bgp_static->igpnexthop;
- attr.med = bgp_static->igpmetric;
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
- if (bgp_static->atomic)
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
- /* Apply route-map. */
- if (bgp_static->rmap.name)
- {
- struct attr attr_tmp = attr;
- info.peer = bgp->peer_self;
- info.attr = &attr_tmp;
- SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
- ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info);
- bgp->peer_self->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- /* Free uninterned attribute. */
- bgp_attr_flush (&attr_tmp);
- /* Unintern original. */
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- bgp_static_withdraw (bgp, p, afi, safi);
- return;
- }
- attr_new = bgp_attr_intern (&attr_tmp);
- }
- else
- attr_new = bgp_attr_intern (&attr);
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_STATIC)
- break;
- if (ri)
- {
- if (attrhash_cmp (ri->attr, attr_new) &&
- !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
- {
- bgp_unlock_node (rn);
- bgp_attr_unintern (&attr_new);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- return;
- }
- else
- {
- /* The attribute is changed. */
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- /* Rewrite BGP route information. */
- if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
- bgp_info_restore(rn, ri);
- else
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- bgp_attr_unintern (&ri->attr);
- ri->attr = attr_new;
- ri->uptime = bgp_clock ();
- /* Process change. */
- bgp_aggregate_increment (bgp, p, ri, afi, safi);
- bgp_process (bgp, rn, afi, safi);
- bgp_unlock_node (rn);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- return;
- }
- }
- /* Make new BGP info. */
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_STATIC;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = attr_new;
- new->uptime = bgp_clock ();
- /* Aggregate address increment. */
- bgp_aggregate_increment (bgp, p, new, afi, safi);
-
- /* Register new BGP information. */
- bgp_info_add (rn, new);
-
- /* route_node_get lock */
- bgp_unlock_node (rn);
-
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- /* Unintern original. */
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- }
- void
- bgp_static_update (struct bgp *bgp, struct prefix *p,
- struct bgp_static *bgp_static, afi_t afi, safi_t safi)
- {
- struct peer *rsclient;
- struct listnode *node, *nnode;
- bgp_static_update_main (bgp, p, bgp_static, afi, safi);
- for (ALL_LIST_ELEMENTS (bgp->rsclient, node, nnode, rsclient))
- {
- if (CHECK_FLAG (rsclient->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- bgp_static_update_rsclient (rsclient, p, bgp_static, afi, safi);
- }
- }
- static void
- bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
- safi_t safi, struct prefix_rd *prd, u_char *tag)
- {
- struct bgp_node *rn;
- struct bgp_info *new;
-
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
- /* Make new BGP info. */
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_STATIC;
- new->peer = bgp->peer_self;
- new->attr = bgp_attr_default_intern (BGP_ORIGIN_IGP);
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->uptime = bgp_clock ();
- new->extra = bgp_info_extra_new();
- memcpy (new->extra->tag, tag, 3);
- /* Aggregate address increment. */
- bgp_aggregate_increment (bgp, p, new, afi, safi);
-
- /* Register new BGP information. */
- bgp_info_add (rn, new);
- /* route_node_get lock */
- bgp_unlock_node (rn);
-
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- }
- void
- bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
- safi_t safi)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, NULL);
- /* Check selected route and self inserted route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self
- && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_STATIC)
- break;
- /* Withdraw static BGP route from routing table. */
- if (ri)
- {
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- bgp_info_delete (rn, ri);
- bgp_process (bgp, rn, afi, safi);
- }
- /* Unlock bgp_node_lookup. */
- bgp_unlock_node (rn);
- }
- void
- bgp_check_local_routes_rsclient (struct peer *rsclient, afi_t afi, safi_t safi)
- {
- struct bgp_static *bgp_static;
- struct bgp *bgp;
- struct bgp_node *rn;
- struct prefix *p;
- bgp = rsclient->bgp;
- for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
- if ((bgp_static = rn->info) != NULL)
- {
- p = &rn->p;
- bgp_static_update_rsclient (rsclient, p, bgp_static,
- afi, safi);
- }
- }
- static void
- bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
- safi_t safi, struct prefix_rd *prd, u_char *tag)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
- /* Check selected route and self inserted route. */
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self
- && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_STATIC)
- break;
- /* Withdraw static BGP route from routing table. */
- if (ri)
- {
- bgp_aggregate_decrement (bgp, p, ri, afi, safi);
- bgp_info_delete (rn, ri);
- bgp_process (bgp, rn, afi, safi);
- }
- /* Unlock bgp_node_lookup. */
- bgp_unlock_node (rn);
- }
- /* Configure static BGP network. When user don't run zebra, static
- route should be installed as valid. */
- static int
- bgp_static_set (struct vty *vty, struct bgp *bgp, const char *ip_str,
- afi_t afi, safi_t safi, const char *rmap, int backdoor)
- {
- int ret;
- struct prefix p;
- struct bgp_static *bgp_static;
- struct bgp_node *rn;
- u_char need_update = 0;
- /* Convert IP prefix string to struct prefix. */
- ret = str2prefix (ip_str, &p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- #ifdef HAVE_IPV6
- if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
- {
- vty_out (vty, "%% Malformed prefix (link-local address)%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- #endif /* HAVE_IPV6 */
- apply_mask (&p);
- /* Set BGP static route configuration. */
- rn = bgp_node_get (bgp->route[afi][safi], &p);
- if (rn->info)
- {
- /* Configuration change. */
- bgp_static = rn->info;
- /* Check previous routes are installed into BGP. */
- if (bgp_static->valid && bgp_static->backdoor != backdoor)
- need_update = 1;
-
- bgp_static->backdoor = backdoor;
-
- if (rmap)
- {
- if (bgp_static->rmap.name)
- free (bgp_static->rmap.name);
- bgp_static->rmap.name = strdup (rmap);
- bgp_static->rmap.map = route_map_lookup_by_name (rmap);
- }
- else
- {
- if (bgp_static->rmap.name)
- free (bgp_static->rmap.name);
- bgp_static->rmap.name = NULL;
- bgp_static->rmap.map = NULL;
- bgp_static->valid = 0;
- }
- bgp_unlock_node (rn);
- }
- else
- {
- /* New configuration. */
- bgp_static = bgp_static_new ();
- bgp_static->backdoor = backdoor;
- bgp_static->valid = 0;
- bgp_static->igpmetric = 0;
- bgp_static->igpnexthop.s_addr = 0;
-
- if (rmap)
- {
- if (bgp_static->rmap.name)
- free (bgp_static->rmap.name);
- bgp_static->rmap.name = strdup (rmap);
- bgp_static->rmap.map = route_map_lookup_by_name (rmap);
- }
- rn->info = bgp_static;
- }
- /* If BGP scan is not enabled, we should install this route here. */
- if (! bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
- {
- bgp_static->valid = 1;
- if (need_update)
- bgp_static_withdraw (bgp, &p, afi, safi);
- if (! bgp_static->backdoor)
- bgp_static_update (bgp, &p, bgp_static, afi, safi);
- }
- return CMD_SUCCESS;
- }
- /* Configure static BGP network. */
- static int
- bgp_static_unset (struct vty *vty, struct bgp *bgp, const char *ip_str,
- afi_t afi, safi_t safi)
- {
- int ret;
- struct prefix p;
- struct bgp_static *bgp_static;
- struct bgp_node *rn;
- /* Convert IP prefix string to struct prefix. */
- ret = str2prefix (ip_str, &p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- #ifdef HAVE_IPV6
- if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
- {
- vty_out (vty, "%% Malformed prefix (link-local address)%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- #endif /* HAVE_IPV6 */
- apply_mask (&p);
- rn = bgp_node_lookup (bgp->route[afi][safi], &p);
- if (! rn)
- {
- vty_out (vty, "%% Can't find specified static route configuration.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- bgp_static = rn->info;
-
- /* Update BGP RIB. */
- if (! bgp_static->backdoor)
- bgp_static_withdraw (bgp, &p, afi, safi);
- /* Clear configuration. */
- bgp_static_free (bgp_static);
- rn->info = NULL;
- bgp_unlock_node (rn);
- bgp_unlock_node (rn);
- return CMD_SUCCESS;
- }
- /* Called from bgp_delete(). Delete all static routes from the BGP
- instance. */
- void
- bgp_static_delete (struct bgp *bgp)
- {
- afi_t afi;
- safi_t safi;
- struct bgp_node *rn;
- struct bgp_node *rm;
- struct bgp_table *table;
- struct bgp_static *bgp_static;
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
- for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
- if (rn->info != NULL)
- {
- if (safi == SAFI_MPLS_VPN)
- {
- table = rn->info;
- for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
- {
- bgp_static = rn->info;
- bgp_static_withdraw_vpnv4 (bgp, &rm->p,
- AFI_IP, SAFI_MPLS_VPN,
- (struct prefix_rd *)&rn->p,
- bgp_static->tag);
- bgp_static_free (bgp_static);
- rn->info = NULL;
- bgp_unlock_node (rn);
- }
- }
- else
- {
- bgp_static = rn->info;
- bgp_static_withdraw (bgp, &rn->p, afi, safi);
- bgp_static_free (bgp_static);
- rn->info = NULL;
- bgp_unlock_node (rn);
- }
- }
- }
- int
- bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
- const char *tag_str)
- {
- int ret;
- struct prefix p;
- struct prefix_rd prd;
- struct bgp *bgp;
- struct bgp_node *prn;
- struct bgp_node *rn;
- struct bgp_table *table;
- struct bgp_static *bgp_static;
- u_char tag[3];
- bgp = vty->index;
- ret = str2prefix (ip_str, &p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- apply_mask (&p);
- ret = str2prefix_rd (rd_str, &prd);
- if (! ret)
- {
- vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- ret = str2tag (tag_str, tag);
- if (! ret)
- {
- vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
- (struct prefix *)&prd);
- if (prn->info == NULL)
- prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
- else
- bgp_unlock_node (prn);
- table = prn->info;
- rn = bgp_node_get (table, &p);
- if (rn->info)
- {
- vty_out (vty, "%% Same network configuration exists%s", VTY_NEWLINE);
- bgp_unlock_node (rn);
- }
- else
- {
- /* New configuration. */
- bgp_static = bgp_static_new ();
- bgp_static->valid = 1;
- memcpy (bgp_static->tag, tag, 3);
- rn->info = bgp_static;
- bgp_static_update_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag);
- }
- return CMD_SUCCESS;
- }
- /* Configure static BGP network. */
- int
- bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str,
- const char *rd_str, const char *tag_str)
- {
- int ret;
- struct bgp *bgp;
- struct prefix p;
- struct prefix_rd prd;
- struct bgp_node *prn;
- struct bgp_node *rn;
- struct bgp_table *table;
- struct bgp_static *bgp_static;
- u_char tag[3];
- bgp = vty->index;
- /* Convert IP prefix string to struct prefix. */
- ret = str2prefix (ip_str, &p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- apply_mask (&p);
- ret = str2prefix_rd (rd_str, &prd);
- if (! ret)
- {
- vty_out (vty, "%% Malformed rd%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- ret = str2tag (tag_str, tag);
- if (! ret)
- {
- vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
- (struct prefix *)&prd);
- if (prn->info == NULL)
- prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
- else
- bgp_unlock_node (prn);
- table = prn->info;
- rn = bgp_node_lookup (table, &p);
- if (rn)
- {
- bgp_static_withdraw_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag);
- bgp_static = rn->info;
- bgp_static_free (bgp_static);
- rn->info = NULL;
- bgp_unlock_node (rn);
- bgp_unlock_node (rn);
- }
- else
- vty_out (vty, "%% Can't find the route%s", VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- DEFUN (bgp_network,
- bgp_network_cmd,
- "network A.B.C.D/M",
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- return bgp_static_set (vty, vty->index, argv[0],
- AFI_IP, bgp_node_safi (vty), NULL, 0);
- }
- DEFUN (bgp_network_route_map,
- bgp_network_route_map_cmd,
- "network A.B.C.D/M route-map WORD",
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- {
- return bgp_static_set (vty, vty->index, argv[0],
- AFI_IP, bgp_node_safi (vty), argv[1], 0);
- }
- DEFUN (bgp_network_backdoor,
- bgp_network_backdoor_cmd,
- "network A.B.C.D/M backdoor",
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Specify a BGP backdoor route\n")
- {
- return bgp_static_set (vty, vty->index, argv[0], AFI_IP, SAFI_UNICAST,
- NULL, 1);
- }
- DEFUN (bgp_network_mask,
- bgp_network_mask_cmd,
- "network A.B.C.D mask A.B.C.D",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
-
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_set (vty, vty->index, prefix_str,
- AFI_IP, bgp_node_safi (vty), NULL, 0);
- }
- DEFUN (bgp_network_mask_route_map,
- bgp_network_mask_route_map_cmd,
- "network A.B.C.D mask A.B.C.D route-map WORD",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
-
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_set (vty, vty->index, prefix_str,
- AFI_IP, bgp_node_safi (vty), argv[2], 0);
- }
- DEFUN (bgp_network_mask_backdoor,
- bgp_network_mask_backdoor_cmd,
- "network A.B.C.D mask A.B.C.D backdoor",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "Specify a BGP backdoor route\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
-
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST,
- NULL, 1);
- }
- DEFUN (bgp_network_mask_natural,
- bgp_network_mask_natural_cmd,
- "network A.B.C.D",
- "Specify a network to announce via BGP\n"
- "Network number\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_set (vty, vty->index, prefix_str,
- AFI_IP, bgp_node_safi (vty), NULL, 0);
- }
- DEFUN (bgp_network_mask_natural_route_map,
- bgp_network_mask_natural_route_map_cmd,
- "network A.B.C.D route-map WORD",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_set (vty, vty->index, prefix_str,
- AFI_IP, bgp_node_safi (vty), argv[1], 0);
- }
- DEFUN (bgp_network_mask_natural_backdoor,
- bgp_network_mask_natural_backdoor_cmd,
- "network A.B.C.D backdoor",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Specify a BGP backdoor route\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_set (vty, vty->index, prefix_str, AFI_IP, SAFI_UNICAST,
- NULL, 1);
- }
- DEFUN (no_bgp_network,
- no_bgp_network_cmd,
- "no network A.B.C.D/M",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- return bgp_static_unset (vty, vty->index, argv[0], AFI_IP,
- bgp_node_safi (vty));
- }
- ALIAS (no_bgp_network,
- no_bgp_network_route_map_cmd,
- "no network A.B.C.D/M route-map WORD",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- ALIAS (no_bgp_network,
- no_bgp_network_backdoor_cmd,
- "no network A.B.C.D/M backdoor",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Specify a BGP backdoor route\n")
- DEFUN (no_bgp_network_mask,
- no_bgp_network_mask_cmd,
- "no network A.B.C.D mask A.B.C.D",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP,
- bgp_node_safi (vty));
- }
- ALIAS (no_bgp_network_mask,
- no_bgp_network_mask_route_map_cmd,
- "no network A.B.C.D mask A.B.C.D route-map WORD",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- ALIAS (no_bgp_network_mask,
- no_bgp_network_mask_backdoor_cmd,
- "no network A.B.C.D mask A.B.C.D backdoor",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "Specify a BGP backdoor route\n")
- DEFUN (no_bgp_network_mask_natural,
- no_bgp_network_mask_natural_cmd,
- "no network A.B.C.D",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], NULL, prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_static_unset (vty, vty->index, prefix_str, AFI_IP,
- bgp_node_safi (vty));
- }
- ALIAS (no_bgp_network_mask_natural,
- no_bgp_network_mask_natural_route_map_cmd,
- "no network A.B.C.D route-map WORD",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- ALIAS (no_bgp_network_mask_natural,
- no_bgp_network_mask_natural_backdoor_cmd,
- "no network A.B.C.D backdoor",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Specify a BGP backdoor route\n")
- #ifdef HAVE_IPV6
- DEFUN (ipv6_bgp_network,
- ipv6_bgp_network_cmd,
- "network X:X::X:X/M",
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>\n")
- {
- return bgp_static_set (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty),
- NULL, 0);
- }
- DEFUN (ipv6_bgp_network_route_map,
- ipv6_bgp_network_route_map_cmd,
- "network X:X::X:X/M route-map WORD",
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- {
- return bgp_static_set (vty, vty->index, argv[0], AFI_IP6,
- bgp_node_safi (vty), argv[1], 0);
- }
- DEFUN (no_ipv6_bgp_network,
- no_ipv6_bgp_network_cmd,
- "no network X:X::X:X/M",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>\n")
- {
- return bgp_static_unset (vty, vty->index, argv[0], AFI_IP6, bgp_node_safi(vty));
- }
- ALIAS (no_ipv6_bgp_network,
- no_ipv6_bgp_network_route_map_cmd,
- "no network X:X::X:X/M route-map WORD",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>\n"
- "Route-map to modify the attributes\n"
- "Name of the route map\n")
- ALIAS (ipv6_bgp_network,
- old_ipv6_bgp_network_cmd,
- "ipv6 bgp network X:X::X:X/M",
- IPV6_STR
- BGP_STR
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
- ALIAS (no_ipv6_bgp_network,
- old_no_ipv6_bgp_network_cmd,
- "no ipv6 bgp network X:X::X:X/M",
- NO_STR
- IPV6_STR
- BGP_STR
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
- #endif /* HAVE_IPV6 */
- /* stubs for removed AS-Pathlimit commands, kept for config compatibility */
- ALIAS_DEPRECATED (bgp_network,
- bgp_network_ttl_cmd,
- "network A.B.C.D/M pathlimit <0-255>",
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (bgp_network_backdoor,
- bgp_network_backdoor_ttl_cmd,
- "network A.B.C.D/M backdoor pathlimit <0-255>",
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Specify a BGP backdoor route\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (bgp_network_mask,
- bgp_network_mask_ttl_cmd,
- "network A.B.C.D mask A.B.C.D pathlimit <0-255>",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (bgp_network_mask_backdoor,
- bgp_network_mask_backdoor_ttl_cmd,
- "network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "Specify a BGP backdoor route\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (bgp_network_mask_natural,
- bgp_network_mask_natural_ttl_cmd,
- "network A.B.C.D pathlimit <0-255>",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (bgp_network_mask_natural_backdoor,
- bgp_network_mask_natural_backdoor_ttl_cmd,
- "network A.B.C.D backdoor pathlimit (1-255>",
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Specify a BGP backdoor route\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_bgp_network,
- no_bgp_network_ttl_cmd,
- "no network A.B.C.D/M pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_bgp_network,
- no_bgp_network_backdoor_ttl_cmd,
- "no network A.B.C.D/M backdoor pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Specify a BGP backdoor route\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_bgp_network,
- no_bgp_network_mask_ttl_cmd,
- "no network A.B.C.D mask A.B.C.D pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_bgp_network_mask,
- no_bgp_network_mask_backdoor_ttl_cmd,
- "no network A.B.C.D mask A.B.C.D backdoor pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Network mask\n"
- "Network mask\n"
- "Specify a BGP backdoor route\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_bgp_network_mask_natural,
- no_bgp_network_mask_natural_ttl_cmd,
- "no network A.B.C.D pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_bgp_network_mask_natural,
- no_bgp_network_mask_natural_backdoor_ttl_cmd,
- "no network A.B.C.D backdoor pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "Network number\n"
- "Specify a BGP backdoor route\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- #ifdef HAVE_IPV6
- ALIAS_DEPRECATED (ipv6_bgp_network,
- ipv6_bgp_network_ttl_cmd,
- "network X:X::X:X/M pathlimit <0-255>",
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- ALIAS_DEPRECATED (no_ipv6_bgp_network,
- no_ipv6_bgp_network_ttl_cmd,
- "no network X:X::X:X/M pathlimit <0-255>",
- NO_STR
- "Specify a network to announce via BGP\n"
- "IPv6 prefix <network>/<length>\n"
- "AS-Path hopcount limit attribute\n"
- "AS-Pathlimit TTL, in number of AS-Path hops\n")
- #endif /* HAVE_IPV6 */
- /* Aggreagete address:
- advertise-map Set condition to advertise attribute
- as-set Generate AS set path information
- attribute-map Set attributes of aggregate
- route-map Set parameters of aggregate
- summary-only Filter more specific routes from updates
- suppress-map Conditionally filter more specific routes from updates
- <cr>
- */
- struct bgp_aggregate
- {
- /* Summary-only flag. */
- u_char summary_only;
- /* AS set generation. */
- u_char as_set;
- /* Route-map for aggregated route. */
- struct route_map *map;
- /* Suppress-count. */
- unsigned long count;
- /* SAFI configuration. */
- safi_t safi;
- };
- static struct bgp_aggregate *
- bgp_aggregate_new (void)
- {
- return XCALLOC (MTYPE_BGP_AGGREGATE, sizeof (struct bgp_aggregate));
- }
- static void
- bgp_aggregate_free (struct bgp_aggregate *aggregate)
- {
- XFREE (MTYPE_BGP_AGGREGATE, aggregate);
- }
- static void
- bgp_aggregate_route (struct bgp *bgp, struct prefix *p, struct bgp_info *rinew,
- afi_t afi, safi_t safi, struct bgp_info *del,
- struct bgp_aggregate *aggregate)
- {
- struct bgp_table *table;
- struct bgp_node *top;
- struct bgp_node *rn;
- u_char origin;
- struct aspath *aspath = NULL;
- struct aspath *asmerge = NULL;
- struct community *community = NULL;
- struct community *commerge = NULL;
- struct in_addr nexthop;
- u_int32_t med = 0;
- struct bgp_info *ri;
- struct bgp_info *new;
- int first = 1;
- unsigned long match = 0;
- /* Record adding route's nexthop and med. */
- if (rinew)
- {
- nexthop = rinew->attr->nexthop;
- med = rinew->attr->med;
- }
- /* ORIGIN attribute: If at least one route among routes that are
- aggregated has ORIGIN with the value INCOMPLETE, then the
- aggregated route must have the ORIGIN attribute with the value
- INCOMPLETE. Otherwise, if at least one route among routes that
- are aggregated has ORIGIN with the value EGP, then the aggregated
- route must have the origin attribute with the value EGP. In all
- other case the value of the ORIGIN attribute of the aggregated
- route is INTERNAL. */
- origin = BGP_ORIGIN_IGP;
- table = bgp->rib[afi][safi];
- top = bgp_node_get (table, p);
- for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
- if (rn->p.prefixlen > p->prefixlen)
- {
- match = 0;
- for (ri = rn->info; ri; ri = ri->next)
- {
- if (BGP_INFO_HOLDDOWN (ri))
- continue;
- if (del && ri == del)
- continue;
- if (! rinew && first)
- {
- nexthop = ri->attr->nexthop;
- med = ri->attr->med;
- first = 0;
- }
- #ifdef AGGREGATE_NEXTHOP_CHECK
- if (! IPV4_ADDR_SAME (&ri->attr->nexthop, &nexthop)
- || ri->attr->med != med)
- {
- if (aspath)
- aspath_free (aspath);
- if (community)
- community_free (community);
- bgp_unlock_node (rn);
- bgp_unlock_node (top);
- return;
- }
- #endif /* AGGREGATE_NEXTHOP_CHECK */
- if (ri->sub_type != BGP_ROUTE_AGGREGATE)
- {
- if (aggregate->summary_only)
- {
- (bgp_info_extra_get (ri))->suppress++;
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- match++;
- }
- aggregate->count++;
- if (aggregate->as_set)
- {
- if (origin < ri->attr->origin)
- origin = ri->attr->origin;
- if (aspath)
- {
- asmerge = aspath_aggregate (aspath, ri->attr->aspath);
- aspath_free (aspath);
- aspath = asmerge;
- }
- else
- aspath = aspath_dup (ri->attr->aspath);
- if (ri->attr->community)
- {
- if (community)
- {
- commerge = community_merge (community,
- ri->attr->community);
- community = community_uniq_sort (commerge);
- community_free (commerge);
- }
- else
- community = community_dup (ri->attr->community);
- }
- }
- }
- }
- if (match)
- bgp_process (bgp, rn, afi, safi);
- }
- bgp_unlock_node (top);
- if (rinew)
- {
- aggregate->count++;
-
- if (aggregate->summary_only)
- (bgp_info_extra_get (rinew))->suppress++;
- if (aggregate->as_set)
- {
- if (origin < rinew->attr->origin)
- origin = rinew->attr->origin;
- if (aspath)
- {
- asmerge = aspath_aggregate (aspath, rinew->attr->aspath);
- aspath_free (aspath);
- aspath = asmerge;
- }
- else
- aspath = aspath_dup (rinew->attr->aspath);
- if (rinew->attr->community)
- {
- if (community)
- {
- commerge = community_merge (community,
- rinew->attr->community);
- community = community_uniq_sort (commerge);
- community_free (commerge);
- }
- else
- community = community_dup (rinew->attr->community);
- }
- }
- }
- if (aggregate->count > 0)
- {
- rn = bgp_node_get (table, p);
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_AGGREGATE;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = bgp_clock ();
- bgp_info_add (rn, new);
- bgp_unlock_node (rn);
- bgp_process (bgp, rn, afi, safi);
- }
- else
- {
- if (aspath)
- aspath_free (aspath);
- if (community)
- community_free (community);
- }
- }
- void bgp_aggregate_delete (struct bgp *, struct prefix *, afi_t, safi_t,
- struct bgp_aggregate *);
- void
- bgp_aggregate_increment (struct bgp *bgp, struct prefix *p,
- struct bgp_info *ri, afi_t afi, safi_t safi)
- {
- struct bgp_node *child;
- struct bgp_node *rn;
- struct bgp_aggregate *aggregate;
- struct bgp_table *table;
- /* MPLS-VPN aggregation is not yet supported. */
- if (safi == SAFI_MPLS_VPN)
- return;
- table = bgp->aggregate[afi][safi];
- /* No aggregates configured. */
- if (bgp_table_top_nolock (table) == NULL)
- return;
- if (p->prefixlen == 0)
- return;
- if (BGP_INFO_HOLDDOWN (ri))
- return;
- child = bgp_node_get (table, p);
- /* Aggregate address configuration check. */
- for (rn = child; rn; rn = bgp_node_parent_nolock (rn))
- if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen)
- {
- bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate);
- bgp_aggregate_route (bgp, &rn->p, ri, afi, safi, NULL, aggregate);
- }
- bgp_unlock_node (child);
- }
- void
- bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p,
- struct bgp_info *del, afi_t afi, safi_t safi)
- {
- struct bgp_node *child;
- struct bgp_node *rn;
- struct bgp_aggregate *aggregate;
- struct bgp_table *table;
- /* MPLS-VPN aggregation is not yet supported. */
- if (safi == SAFI_MPLS_VPN)
- return;
- table = bgp->aggregate[afi][safi];
- /* No aggregates configured. */
- if (bgp_table_top_nolock (table) == NULL)
- return;
- if (p->prefixlen == 0)
- return;
- child = bgp_node_get (table, p);
- /* Aggregate address configuration check. */
- for (rn = child; rn; rn = bgp_node_parent_nolock (rn))
- if ((aggregate = rn->info) != NULL && rn->p.prefixlen < p->prefixlen)
- {
- bgp_aggregate_delete (bgp, &rn->p, afi, safi, aggregate);
- bgp_aggregate_route (bgp, &rn->p, NULL, afi, safi, del, aggregate);
- }
- bgp_unlock_node (child);
- }
- static void
- bgp_aggregate_add (struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi,
- struct bgp_aggregate *aggregate)
- {
- struct bgp_table *table;
- struct bgp_node *top;
- struct bgp_node *rn;
- struct bgp_info *new;
- struct bgp_info *ri;
- unsigned long match;
- u_char origin = BGP_ORIGIN_IGP;
- struct aspath *aspath = NULL;
- struct aspath *asmerge = NULL;
- struct community *community = NULL;
- struct community *commerge = NULL;
- table = bgp->rib[afi][safi];
- /* Sanity check. */
- if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
- return;
- if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
- return;
-
- /* If routes exists below this node, generate aggregate routes. */
- top = bgp_node_get (table, p);
- for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
- if (rn->p.prefixlen > p->prefixlen)
- {
- match = 0;
- for (ri = rn->info; ri; ri = ri->next)
- {
- if (BGP_INFO_HOLDDOWN (ri))
- continue;
- if (ri->sub_type != BGP_ROUTE_AGGREGATE)
- {
- /* summary-only aggregate route suppress aggregated
- route announcement. */
- if (aggregate->summary_only)
- {
- (bgp_info_extra_get (ri))->suppress++;
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- match++;
- }
- /* as-set aggregate route generate origin, as path,
- community aggregation. */
- if (aggregate->as_set)
- {
- if (origin < ri->attr->origin)
- origin = ri->attr->origin;
- if (aspath)
- {
- asmerge = aspath_aggregate (aspath, ri->attr->aspath);
- aspath_free (aspath);
- aspath = asmerge;
- }
- else
- aspath = aspath_dup (ri->attr->aspath);
- if (ri->attr->community)
- {
- if (community)
- {
- commerge = community_merge (community,
- ri->attr->community);
- community = community_uniq_sort (commerge);
- community_free (commerge);
- }
- else
- community = community_dup (ri->attr->community);
- }
- }
- aggregate->count++;
- }
- }
-
- /* If this node is suppressed, process the change. */
- if (match)
- bgp_process (bgp, rn, afi, safi);
- }
- bgp_unlock_node (top);
- /* Add aggregate route to BGP table. */
- if (aggregate->count)
- {
- rn = bgp_node_get (table, p);
- new = bgp_info_new ();
- new->type = ZEBRA_ROUTE_BGP;
- new->sub_type = BGP_ROUTE_AGGREGATE;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = bgp_attr_aggregate_intern (bgp, origin, aspath, community, aggregate->as_set);
- new->uptime = bgp_clock ();
- bgp_info_add (rn, new);
- bgp_unlock_node (rn);
-
- /* Process change. */
- bgp_process (bgp, rn, afi, safi);
- }
- }
- void
- bgp_aggregate_delete (struct bgp *bgp, struct prefix *p, afi_t afi,
- safi_t safi, struct bgp_aggregate *aggregate)
- {
- struct bgp_table *table;
- struct bgp_node *top;
- struct bgp_node *rn;
- struct bgp_info *ri;
- unsigned long match;
- table = bgp->rib[afi][safi];
- if (afi == AFI_IP && p->prefixlen == IPV4_MAX_BITLEN)
- return;
- if (afi == AFI_IP6 && p->prefixlen == IPV6_MAX_BITLEN)
- return;
- /* If routes exists below this node, generate aggregate routes. */
- top = bgp_node_get (table, p);
- for (rn = bgp_node_get (table, p); rn; rn = bgp_route_next_until (rn, top))
- if (rn->p.prefixlen > p->prefixlen)
- {
- match = 0;
- for (ri = rn->info; ri; ri = ri->next)
- {
- if (BGP_INFO_HOLDDOWN (ri))
- continue;
- if (ri->sub_type != BGP_ROUTE_AGGREGATE)
- {
- if (aggregate->summary_only && ri->extra)
- {
- ri->extra->suppress--;
- if (ri->extra->suppress == 0)
- {
- bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
- match++;
- }
- }
- aggregate->count--;
- }
- }
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process (bgp, rn, afi, safi);
- }
- bgp_unlock_node (top);
- /* Delete aggregate route from BGP table. */
- rn = bgp_node_get (table, p);
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self
- && ri->type == ZEBRA_ROUTE_BGP
- && ri->sub_type == BGP_ROUTE_AGGREGATE)
- break;
- /* Withdraw static BGP route from routing table. */
- if (ri)
- {
- bgp_info_delete (rn, ri);
- bgp_process (bgp, rn, afi, safi);
- }
- /* Unlock bgp_node_lookup. */
- bgp_unlock_node (rn);
- }
- /* Aggregate route attribute. */
- #define AGGREGATE_SUMMARY_ONLY 1
- #define AGGREGATE_AS_SET 1
- static int
- bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
- afi_t afi, safi_t safi)
- {
- int ret;
- struct prefix p;
- struct bgp_node *rn;
- struct bgp *bgp;
- struct bgp_aggregate *aggregate;
- /* Convert string to prefix structure. */
- ret = str2prefix (prefix_str, &p);
- if (!ret)
- {
- vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- apply_mask (&p);
- /* Get BGP structure. */
- bgp = vty->index;
- /* Old configuration check. */
- rn = bgp_node_lookup (bgp->aggregate[afi][safi], &p);
- if (! rn)
- {
- vty_out (vty, "%% There is no aggregate-address configuration.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- aggregate = rn->info;
- if (aggregate->safi & SAFI_UNICAST)
- bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
- if (aggregate->safi & SAFI_MULTICAST)
- bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
- /* Unlock aggregate address configuration. */
- rn->info = NULL;
- bgp_aggregate_free (aggregate);
- bgp_unlock_node (rn);
- bgp_unlock_node (rn);
- return CMD_SUCCESS;
- }
- static int
- bgp_aggregate_set (struct vty *vty, const char *prefix_str,
- afi_t afi, safi_t safi,
- u_char summary_only, u_char as_set)
- {
- int ret;
- struct prefix p;
- struct bgp_node *rn;
- struct bgp *bgp;
- struct bgp_aggregate *aggregate;
- /* Convert string to prefix structure. */
- ret = str2prefix (prefix_str, &p);
- if (!ret)
- {
- vty_out (vty, "Malformed prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- apply_mask (&p);
- /* Get BGP structure. */
- bgp = vty->index;
- /* Old configuration check. */
- rn = bgp_node_get (bgp->aggregate[afi][safi], &p);
- if (rn->info)
- {
- vty_out (vty, "There is already same aggregate network.%s", VTY_NEWLINE);
- /* try to remove the old entry */
- ret = bgp_aggregate_unset (vty, prefix_str, afi, safi);
- if (ret)
- {
- vty_out (vty, "Error deleting aggregate.%s", VTY_NEWLINE);
- bgp_unlock_node (rn);
- return CMD_WARNING;
- }
- }
- /* Make aggregate address structure. */
- aggregate = bgp_aggregate_new ();
- aggregate->summary_only = summary_only;
- aggregate->as_set = as_set;
- aggregate->safi = safi;
- rn->info = aggregate;
- /* Aggregate address insert into BGP routing table. */
- if (safi & SAFI_UNICAST)
- bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
- if (safi & SAFI_MULTICAST)
- bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
- return CMD_SUCCESS;
- }
- DEFUN (aggregate_address,
- aggregate_address_cmd,
- "aggregate-address A.B.C.D/M",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n")
- {
- return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty), 0, 0);
- }
- DEFUN (aggregate_address_mask,
- aggregate_address_mask_cmd,
- "aggregate-address A.B.C.D A.B.C.D",
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
- 0, 0);
- }
- DEFUN (aggregate_address_summary_only,
- aggregate_address_summary_only_cmd,
- "aggregate-address A.B.C.D/M summary-only",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n")
- {
- return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty),
- AGGREGATE_SUMMARY_ONLY, 0);
- }
- DEFUN (aggregate_address_mask_summary_only,
- aggregate_address_mask_summary_only_cmd,
- "aggregate-address A.B.C.D A.B.C.D summary-only",
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Filter more specific routes from updates\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
- AGGREGATE_SUMMARY_ONLY, 0);
- }
- DEFUN (aggregate_address_as_set,
- aggregate_address_as_set_cmd,
- "aggregate-address A.B.C.D/M as-set",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n")
- {
- return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty),
- 0, AGGREGATE_AS_SET);
- }
- DEFUN (aggregate_address_mask_as_set,
- aggregate_address_mask_as_set_cmd,
- "aggregate-address A.B.C.D A.B.C.D as-set",
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Generate AS set path information\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
- 0, AGGREGATE_AS_SET);
- }
- DEFUN (aggregate_address_as_set_summary,
- aggregate_address_as_set_summary_cmd,
- "aggregate-address A.B.C.D/M as-set summary-only",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n")
- {
- return bgp_aggregate_set (vty, argv[0], AFI_IP, bgp_node_safi (vty),
- AGGREGATE_SUMMARY_ONLY, AGGREGATE_AS_SET);
- }
- ALIAS (aggregate_address_as_set_summary,
- aggregate_address_summary_as_set_cmd,
- "aggregate-address A.B.C.D/M summary-only as-set",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n")
- DEFUN (aggregate_address_mask_as_set_summary,
- aggregate_address_mask_as_set_summary_cmd,
- "aggregate-address A.B.C.D A.B.C.D as-set summary-only",
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_aggregate_set (vty, prefix_str, AFI_IP, bgp_node_safi (vty),
- AGGREGATE_SUMMARY_ONLY, AGGREGATE_AS_SET);
- }
- ALIAS (aggregate_address_mask_as_set_summary,
- aggregate_address_mask_summary_as_set_cmd,
- "aggregate-address A.B.C.D A.B.C.D summary-only as-set",
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n")
- DEFUN (no_aggregate_address,
- no_aggregate_address_cmd,
- "no aggregate-address A.B.C.D/M",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n")
- {
- return bgp_aggregate_unset (vty, argv[0], AFI_IP, bgp_node_safi (vty));
- }
- ALIAS (no_aggregate_address,
- no_aggregate_address_summary_only_cmd,
- "no aggregate-address A.B.C.D/M summary-only",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n")
- ALIAS (no_aggregate_address,
- no_aggregate_address_as_set_cmd,
- "no aggregate-address A.B.C.D/M as-set",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n")
- ALIAS (no_aggregate_address,
- no_aggregate_address_as_set_summary_cmd,
- "no aggregate-address A.B.C.D/M as-set summary-only",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n")
- ALIAS (no_aggregate_address,
- no_aggregate_address_summary_as_set_cmd,
- "no aggregate-address A.B.C.D/M summary-only as-set",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n")
- DEFUN (no_aggregate_address_mask,
- no_aggregate_address_mask_cmd,
- "no aggregate-address A.B.C.D A.B.C.D",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n")
- {
- int ret;
- char prefix_str[BUFSIZ];
- ret = netmask_str2prefix_str (argv[0], argv[1], prefix_str);
- if (! ret)
- {
- vty_out (vty, "%% Inconsistent address and mask%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_aggregate_unset (vty, prefix_str, AFI_IP, bgp_node_safi (vty));
- }
- ALIAS (no_aggregate_address_mask,
- no_aggregate_address_mask_summary_only_cmd,
- "no aggregate-address A.B.C.D A.B.C.D summary-only",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Filter more specific routes from updates\n")
- ALIAS (no_aggregate_address_mask,
- no_aggregate_address_mask_as_set_cmd,
- "no aggregate-address A.B.C.D A.B.C.D as-set",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Generate AS set path information\n")
- ALIAS (no_aggregate_address_mask,
- no_aggregate_address_mask_as_set_summary_cmd,
- "no aggregate-address A.B.C.D A.B.C.D as-set summary-only",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n")
- ALIAS (no_aggregate_address_mask,
- no_aggregate_address_mask_summary_as_set_cmd,
- "no aggregate-address A.B.C.D A.B.C.D summary-only as-set",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n")
- #ifdef HAVE_IPV6
- DEFUN (ipv6_aggregate_address,
- ipv6_aggregate_address_cmd,
- "aggregate-address X:X::X:X/M",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n")
- {
- return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST, 0, 0);
- }
- DEFUN (ipv6_aggregate_address_summary_only,
- ipv6_aggregate_address_summary_only_cmd,
- "aggregate-address X:X::X:X/M summary-only",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n")
- {
- return bgp_aggregate_set (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- AGGREGATE_SUMMARY_ONLY, 0);
- }
- DEFUN (no_ipv6_aggregate_address,
- no_ipv6_aggregate_address_cmd,
- "no aggregate-address X:X::X:X/M",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n")
- {
- return bgp_aggregate_unset (vty, argv[0], AFI_IP6, SAFI_UNICAST);
- }
- DEFUN (no_ipv6_aggregate_address_summary_only,
- no_ipv6_aggregate_address_summary_only_cmd,
- "no aggregate-address X:X::X:X/M summary-only",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n")
- {
- return bgp_aggregate_unset (vty, argv[0], AFI_IP6, SAFI_UNICAST);
- }
- ALIAS (ipv6_aggregate_address,
- old_ipv6_aggregate_address_cmd,
- "ipv6 bgp aggregate-address X:X::X:X/M",
- IPV6_STR
- BGP_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n")
- ALIAS (ipv6_aggregate_address_summary_only,
- old_ipv6_aggregate_address_summary_only_cmd,
- "ipv6 bgp aggregate-address X:X::X:X/M summary-only",
- IPV6_STR
- BGP_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n")
- ALIAS (no_ipv6_aggregate_address,
- old_no_ipv6_aggregate_address_cmd,
- "no ipv6 bgp aggregate-address X:X::X:X/M",
- NO_STR
- IPV6_STR
- BGP_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n")
- ALIAS (no_ipv6_aggregate_address_summary_only,
- old_no_ipv6_aggregate_address_summary_only_cmd,
- "no ipv6 bgp aggregate-address X:X::X:X/M summary-only",
- NO_STR
- IPV6_STR
- BGP_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Filter more specific routes from updates\n")
- #endif /* HAVE_IPV6 */
- /* Redistribute route treatment. */
- void
- bgp_redistribute_add (struct prefix *p, const struct in_addr *nexthop,
- const struct in6_addr *nexthop6,
- u_int32_t metric, u_char type)
- {
- struct bgp *bgp;
- struct listnode *node, *nnode;
- struct bgp_info *new;
- struct bgp_info *bi;
- struct bgp_info info;
- struct bgp_node *bn;
- struct attr attr;
- struct attr *new_attr;
- afi_t afi;
- int ret;
- /* Make default attribute. */
- bgp_attr_default_set (&attr, BGP_ORIGIN_INCOMPLETE);
- if (nexthop)
- attr.nexthop = *nexthop;
- #ifdef HAVE_IPV6
- if (nexthop6)
- {
- struct attr_extra *extra = bgp_attr_extra_get(&attr);
- extra->mp_nexthop_global = *nexthop6;
- extra->mp_nexthop_len = 16;
- }
- #endif
- attr.med = metric;
- attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
- for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
- {
- afi = family2afi (p->family);
- if (bgp->redist[afi][type])
- {
- struct attr attr_new;
- struct attr_extra extra_new;
- /* Copy attribute for modification. */
- attr_new.extra = &extra_new;
- bgp_attr_dup (&attr_new, &attr);
- if (bgp->redist_metric_flag[afi][type])
- attr_new.med = bgp->redist_metric[afi][type];
- /* Apply route-map. */
- if (bgp->rmap[afi][type].map)
- {
- info.peer = bgp->peer_self;
- info.attr = &attr_new;
- SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE);
- ret = route_map_apply (bgp->rmap[afi][type].map, p, RMAP_BGP,
- &info);
- bgp->peer_self->rmap_type = 0;
- if (ret == RMAP_DENYMATCH)
- {
- /* Free uninterned attribute. */
- bgp_attr_flush (&attr_new);
- /* Unintern original. */
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- bgp_redistribute_delete (p, type);
- return;
- }
- }
- bn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST],
- afi, SAFI_UNICAST, p, NULL);
-
- new_attr = bgp_attr_intern (&attr_new);
- for (bi = bn->info; bi; bi = bi->next)
- if (bi->peer == bgp->peer_self
- && bi->sub_type == BGP_ROUTE_REDISTRIBUTE)
- break;
-
- if (bi)
- {
- if (attrhash_cmp (bi->attr, new_attr) &&
- !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
- {
- bgp_attr_unintern (&new_attr);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- bgp_unlock_node (bn);
- return;
- }
- else
- {
- /* The attribute is changed. */
- bgp_info_set_flag (bn, bi, BGP_INFO_ATTR_CHANGED);
-
- /* Rewrite BGP route information. */
- if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED))
- bgp_info_restore(bn, bi);
- else
- bgp_aggregate_decrement (bgp, p, bi, afi, SAFI_UNICAST);
- bgp_attr_unintern (&bi->attr);
- bi->attr = new_attr;
- bi->uptime = bgp_clock ();
-
- /* Process change. */
- bgp_aggregate_increment (bgp, p, bi, afi, SAFI_UNICAST);
- bgp_process (bgp, bn, afi, SAFI_UNICAST);
- bgp_unlock_node (bn);
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- return;
- }
- }
- new = bgp_info_new ();
- new->type = type;
- new->sub_type = BGP_ROUTE_REDISTRIBUTE;
- new->peer = bgp->peer_self;
- SET_FLAG (new->flags, BGP_INFO_VALID);
- new->attr = new_attr;
- new->uptime = bgp_clock ();
- bgp_aggregate_increment (bgp, p, new, afi, SAFI_UNICAST);
- bgp_info_add (bn, new);
- bgp_unlock_node (bn);
- bgp_process (bgp, bn, afi, SAFI_UNICAST);
- }
- }
- /* Unintern original. */
- aspath_unintern (&attr.aspath);
- bgp_attr_extra_free (&attr);
- }
- void
- bgp_redistribute_delete (struct prefix *p, u_char type)
- {
- struct bgp *bgp;
- struct listnode *node, *nnode;
- afi_t afi;
- struct bgp_node *rn;
- struct bgp_info *ri;
- for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
- {
- afi = family2afi (p->family);
- if (bgp->redist[afi][type])
- {
- rn = bgp_afi_node_get (bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL);
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self
- && ri->type == type)
- break;
- if (ri)
- {
- bgp_aggregate_decrement (bgp, p, ri, afi, SAFI_UNICAST);
- bgp_info_delete (rn, ri);
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
- }
- bgp_unlock_node (rn);
- }
- }
- }
- /* Withdraw specified route type's route. */
- void
- bgp_redistribute_withdraw (struct bgp *bgp, afi_t afi, int type)
- {
- struct bgp_node *rn;
- struct bgp_info *ri;
- struct bgp_table *table;
- table = bgp->rib[afi][SAFI_UNICAST];
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- {
- for (ri = rn->info; ri; ri = ri->next)
- if (ri->peer == bgp->peer_self
- && ri->type == type)
- break;
- if (ri)
- {
- bgp_aggregate_decrement (bgp, &rn->p, ri, afi, SAFI_UNICAST);
- bgp_info_delete (rn, ri);
- bgp_process (bgp, rn, afi, SAFI_UNICAST);
- }
- }
- }
- /* Static function to display route. */
- static void
- route_vty_out_route (struct prefix *p, struct vty *vty)
- {
- int len;
- u_int32_t destination;
- char buf[BUFSIZ];
- if (p->family == AF_INET)
- {
- len = vty_out (vty, "%s", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ));
- destination = ntohl (p->u.prefix4.s_addr);
- if ((IN_CLASSC (destination) && p->prefixlen == 24)
- || (IN_CLASSB (destination) && p->prefixlen == 16)
- || (IN_CLASSA (destination) && p->prefixlen == 8)
- || p->u.prefix4.s_addr == 0)
- {
- /* When mask is natural, mask is not displayed. */
- }
- else
- len += vty_out (vty, "/%d", p->prefixlen);
- }
- else
- len = vty_out (vty, "%s/%d", inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
- p->prefixlen);
- len = 17 - len;
- if (len < 1)
- vty_out (vty, "%s%*s", VTY_NEWLINE, 20, " ");
- else
- vty_out (vty, "%*s", len, " ");
- }
- enum bgp_display_type
- {
- normal_list,
- };
- /* Print the short form route status for a bgp_info */
- static void
- route_vty_short_status_out (struct vty *vty, struct bgp_info *binfo)
- {
- /* Route status display. */
- if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
- vty_out (vty, "R");
- else if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
- vty_out (vty, "S");
- else if (binfo->extra && binfo->extra->suppress)
- vty_out (vty, "s");
- else if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
- vty_out (vty, "*");
- else
- vty_out (vty, " ");
- /* Selected */
- if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
- vty_out (vty, "h");
- else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
- vty_out (vty, "d");
- else if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
- vty_out (vty, ">");
- else
- vty_out (vty, " ");
- /* Internal route. */
- if ((binfo->peer->as) && (binfo->peer->as == binfo->peer->local_as))
- vty_out (vty, "i");
- else
- vty_out (vty, " ");
- }
- /* called from terminal list command */
- void
- route_vty_out (struct vty *vty, struct prefix *p,
- struct bgp_info *binfo, int display, safi_t safi)
- {
- struct attr *attr;
-
- /* short status lead text */
- route_vty_short_status_out (vty, binfo);
-
- /* print prefix and mask */
- if (! display)
- route_vty_out_route (p, vty);
- else
- vty_out (vty, "%*s", 17, " ");
- /* Print attribute */
- attr = binfo->attr;
- if (attr)
- {
- if (p->family == AF_INET)
- {
- if (safi == SAFI_MPLS_VPN)
- vty_out (vty, "%-16s",
- inet_ntoa (attr->extra->mp_nexthop_global_in));
- else
- vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
- }
- #ifdef HAVE_IPV6
- else if (p->family == AF_INET6)
- {
- int len;
- char buf[BUFSIZ];
- len = vty_out (vty, "%s",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
- buf, BUFSIZ));
- len = 16 - len;
- if (len < 1)
- vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
- else
- vty_out (vty, "%*s", len, " ");
- }
- #endif /* HAVE_IPV6 */
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
- vty_out (vty, "%10u", attr->med);
- else
- vty_out (vty, " ");
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- vty_out (vty, "%7u", attr->local_pref);
- else
- vty_out (vty, " ");
- vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
-
- /* Print aspath */
- if (attr->aspath)
- aspath_print_vty (vty, "%s", attr->aspath, " ");
- /* Print origin */
- vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- /* called from terminal list command */
- void
- route_vty_out_tmp (struct vty *vty, struct prefix *p,
- struct attr *attr, safi_t safi)
- {
- /* Route status display. */
- vty_out (vty, "*");
- vty_out (vty, ">");
- vty_out (vty, " ");
- /* print prefix and mask */
- route_vty_out_route (p, vty);
- /* Print attribute */
- if (attr)
- {
- if (p->family == AF_INET)
- {
- if (safi == SAFI_MPLS_VPN)
- vty_out (vty, "%-16s",
- inet_ntoa (attr->extra->mp_nexthop_global_in));
- else
- vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
- }
- #ifdef HAVE_IPV6
- else if (p->family == AF_INET6)
- {
- int len;
- char buf[BUFSIZ];
-
- assert (attr->extra);
- len = vty_out (vty, "%s",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
- buf, BUFSIZ));
- len = 16 - len;
- if (len < 1)
- vty_out (vty, "%s%*s", VTY_NEWLINE, 36, " ");
- else
- vty_out (vty, "%*s", len, " ");
- }
- #endif /* HAVE_IPV6 */
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))
- vty_out (vty, "%10u", attr->med);
- else
- vty_out (vty, " ");
- if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))
- vty_out (vty, "%7u", attr->local_pref);
- else
- vty_out (vty, " ");
-
- vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
-
- /* Print aspath */
- if (attr->aspath)
- aspath_print_vty (vty, "%s", attr->aspath, " ");
- /* Print origin */
- vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- void
- route_vty_out_tag (struct vty *vty, struct prefix *p,
- struct bgp_info *binfo, int display, safi_t safi)
- {
- struct attr *attr;
- u_int32_t label = 0;
-
- if (!binfo->extra)
- return;
-
- /* short status lead text */
- route_vty_short_status_out (vty, binfo);
-
- /* print prefix and mask */
- if (! display)
- route_vty_out_route (p, vty);
- else
- vty_out (vty, "%*s", 17, " ");
- /* Print attribute */
- attr = binfo->attr;
- if (attr)
- {
- if (p->family == AF_INET)
- {
- if (safi == SAFI_MPLS_VPN)
- vty_out (vty, "%-16s",
- inet_ntoa (attr->extra->mp_nexthop_global_in));
- else
- vty_out (vty, "%-16s", inet_ntoa (attr->nexthop));
- }
- #ifdef HAVE_IPV6
- else if (p->family == AF_INET6)
- {
- assert (attr->extra);
- char buf[BUFSIZ];
- char buf1[BUFSIZ];
- if (attr->extra->mp_nexthop_len == 16)
- vty_out (vty, "%s",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
- buf, BUFSIZ));
- else if (attr->extra->mp_nexthop_len == 32)
- vty_out (vty, "%s(%s)",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
- buf, BUFSIZ),
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
- buf1, BUFSIZ));
-
- }
- #endif /* HAVE_IPV6 */
- }
- label = decode_label (binfo->extra->tag);
- vty_out (vty, "notag/%d", label);
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- /* dampening route */
- static void
- damp_route_vty_out (struct vty *vty, struct prefix *p,
- struct bgp_info *binfo, int display, safi_t safi)
- {
- struct attr *attr;
- int len;
- char timebuf[BGP_UPTIME_LEN];
- /* short status lead text */
- route_vty_short_status_out (vty, binfo);
-
- /* print prefix and mask */
- if (! display)
- route_vty_out_route (p, vty);
- else
- vty_out (vty, "%*s", 17, " ");
- len = vty_out (vty, "%s", binfo->peer->host);
- len = 17 - len;
- if (len < 1)
- vty_out (vty, "%s%*s", VTY_NEWLINE, 34, " ");
- else
- vty_out (vty, "%*s", len, " ");
- vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN));
- /* Print attribute */
- attr = binfo->attr;
- if (attr)
- {
- /* Print aspath */
- if (attr->aspath)
- aspath_print_vty (vty, "%s", attr->aspath, " ");
- /* Print origin */
- vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- /* flap route */
- static void
- flap_route_vty_out (struct vty *vty, struct prefix *p,
- struct bgp_info *binfo, int display, safi_t safi)
- {
- struct attr *attr;
- struct bgp_damp_info *bdi;
- char timebuf[BGP_UPTIME_LEN];
- int len;
-
- if (!binfo->extra)
- return;
-
- bdi = binfo->extra->damp_info;
- /* short status lead text */
- route_vty_short_status_out (vty, binfo);
-
- /* print prefix and mask */
- if (! display)
- route_vty_out_route (p, vty);
- else
- vty_out (vty, "%*s", 17, " ");
- len = vty_out (vty, "%s", binfo->peer->host);
- len = 16 - len;
- if (len < 1)
- vty_out (vty, "%s%*s", VTY_NEWLINE, 33, " ");
- else
- vty_out (vty, "%*s", len, " ");
- len = vty_out (vty, "%d", bdi->flap);
- len = 5 - len;
- if (len < 1)
- vty_out (vty, " ");
- else
- vty_out (vty, "%*s ", len, " ");
-
- vty_out (vty, "%s ", peer_uptime (bdi->start_time,
- timebuf, BGP_UPTIME_LEN));
- if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED)
- && ! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
- vty_out (vty, "%s ", bgp_damp_reuse_time_vty (vty, binfo, timebuf, BGP_UPTIME_LEN));
- else
- vty_out (vty, "%*s ", 8, " ");
- /* Print attribute */
- attr = binfo->attr;
- if (attr)
- {
- /* Print aspath */
- if (attr->aspath)
- aspath_print_vty (vty, "%s", attr->aspath, " ");
- /* Print origin */
- vty_out (vty, "%s", bgp_origin_str[attr->origin]);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- static void
- route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
- struct bgp_info *binfo, afi_t afi, safi_t safi)
- {
- char buf[INET6_ADDRSTRLEN];
- char buf1[BUFSIZ];
- struct attr *attr;
- int sockunion_vty_out (struct vty *, union sockunion *);
- #ifdef HAVE_CLOCK_MONOTONIC
- time_t tbuf;
- #endif
-
- attr = binfo->attr;
- if (attr)
- {
- /* Line1 display AS-path, Aggregator */
- if (attr->aspath)
- {
- vty_out (vty, " ");
- if (aspath_count_hops (attr->aspath) == 0)
- vty_out (vty, "Local");
- else
- aspath_print_vty (vty, "%s", attr->aspath, "");
- }
- if (CHECK_FLAG (binfo->flags, BGP_INFO_REMOVED))
- vty_out (vty, ", (removed)");
- if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
- vty_out (vty, ", (stale)");
- if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
- vty_out (vty, ", (aggregated by %u %s)",
- attr->extra->aggregator_as,
- inet_ntoa (attr->extra->aggregator_addr));
- if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
- vty_out (vty, ", (Received from a RR-client)");
- if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
- vty_out (vty, ", (Received from a RS-client)");
- if (CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
- vty_out (vty, ", (history entry)");
- else if (CHECK_FLAG (binfo->flags, BGP_INFO_DAMPED))
- vty_out (vty, ", (suppressed due to dampening)");
- vty_out (vty, "%s", VTY_NEWLINE);
-
- /* Line2 display Next-hop, Neighbor, Router-id */
- if (p->family == AF_INET)
- {
- vty_out (vty, " %s", safi == SAFI_MPLS_VPN ?
- inet_ntoa (attr->extra->mp_nexthop_global_in) :
- inet_ntoa (attr->nexthop));
- }
- #ifdef HAVE_IPV6
- else
- {
- assert (attr->extra);
- vty_out (vty, " %s",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global,
- buf, INET6_ADDRSTRLEN));
- }
- #endif /* HAVE_IPV6 */
- if (binfo->peer == bgp->peer_self)
- {
- vty_out (vty, " from %s ",
- p->family == AF_INET ? "0.0.0.0" : "::");
- vty_out (vty, "(%s)", inet_ntoa(bgp->router_id));
- }
- else
- {
- if (! CHECK_FLAG (binfo->flags, BGP_INFO_VALID))
- vty_out (vty, " (inaccessible)");
- else if (binfo->extra && binfo->extra->igpmetric)
- vty_out (vty, " (metric %u)", binfo->extra->igpmetric);
- vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
- else
- vty_out (vty, " (%s)", inet_ntop (AF_INET, &binfo->peer->remote_id, buf1, BUFSIZ));
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- #ifdef HAVE_IPV6
- /* display nexthop local */
- if (attr->extra && attr->extra->mp_nexthop_len == 32)
- {
- vty_out (vty, " (%s)%s",
- inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local,
- buf, INET6_ADDRSTRLEN),
- VTY_NEWLINE);
- }
- #endif /* HAVE_IPV6 */
- /* Line 3 display Origin, Med, Locpref, Weight, valid, Int/Ext/Local, Atomic, best */
- vty_out (vty, " Origin %s", bgp_origin_long_str[attr->origin]);
-
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
- vty_out (vty, ", metric %u", attr->med);
-
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
- vty_out (vty, ", localpref %u", attr->local_pref);
- else
- vty_out (vty, ", localpref %u", bgp->default_local_pref);
- if (attr->extra && attr->extra->weight != 0)
- vty_out (vty, ", weight %u", attr->extra->weight);
-
- if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
- vty_out (vty, ", valid");
- if (binfo->peer != bgp->peer_self)
- {
- if (binfo->peer->as == binfo->peer->local_as)
- vty_out (vty, ", internal");
- else
- vty_out (vty, ", %s",
- (bgp_confederation_peers_check(bgp, binfo->peer->as) ? "confed-external" : "external"));
- }
- else if (binfo->sub_type == BGP_ROUTE_AGGREGATE)
- vty_out (vty, ", aggregated, local");
- else if (binfo->type != ZEBRA_ROUTE_BGP)
- vty_out (vty, ", sourced");
- else
- vty_out (vty, ", sourced, local");
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
- vty_out (vty, ", atomic-aggregate");
-
- if (CHECK_FLAG (binfo->flags, BGP_INFO_MULTIPATH) ||
- (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED) &&
- bgp_info_mpath_count (binfo)))
- vty_out (vty, ", multipath");
- if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
- vty_out (vty, ", best");
- vty_out (vty, "%s", VTY_NEWLINE);
-
- /* Line 4 display Community */
- if (attr->community)
- vty_out (vty, " Community: %s%s", attr->community->str,
- VTY_NEWLINE);
-
- /* Line 5 display Extended-community */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
- vty_out (vty, " Extended Community: %s%s",
- attr->extra->ecommunity->str, VTY_NEWLINE);
-
- /* Line 6 display Originator, Cluster-id */
- if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) ||
- (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)))
- {
- assert (attr->extra);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
- vty_out (vty, " Originator: %s",
- inet_ntoa (attr->extra->originator_id));
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))
- {
- int i;
- vty_out (vty, ", Cluster list: ");
- for (i = 0; i < attr->extra->cluster->length / 4; i++)
- vty_out (vty, "%s ",
- inet_ntoa (attr->extra->cluster->list[i]));
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
-
- if (binfo->extra && binfo->extra->damp_info)
- bgp_damp_info_vty (vty, binfo);
- /* Line 7 display Uptime */
- #ifdef HAVE_CLOCK_MONOTONIC
- tbuf = time(NULL) - (bgp_clock() - binfo->uptime);
- vty_out (vty, " Last update: %s", ctime(&tbuf));
- #else
- vty_out (vty, " Last update: %s", ctime(&binfo->uptime));
- #endif /* HAVE_CLOCK_MONOTONIC */
- }
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- #define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,%s r RIB-failure, S Stale, R Removed%s"
- #define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s"
- #define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path%s"
- #define BGP_SHOW_DAMP_HEADER " Network From Reuse Path%s"
- #define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path%s"
- enum bgp_show_type
- {
- bgp_show_type_normal,
- bgp_show_type_regexp,
- bgp_show_type_prefix_list,
- bgp_show_type_filter_list,
- bgp_show_type_route_map,
- bgp_show_type_neighbor,
- bgp_show_type_cidr_only,
- bgp_show_type_prefix_longer,
- bgp_show_type_community_all,
- bgp_show_type_community,
- bgp_show_type_community_exact,
- bgp_show_type_community_list,
- bgp_show_type_community_list_exact,
- bgp_show_type_flap_statistics,
- bgp_show_type_flap_address,
- bgp_show_type_flap_prefix,
- bgp_show_type_flap_cidr_only,
- bgp_show_type_flap_regexp,
- bgp_show_type_flap_filter_list,
- bgp_show_type_flap_prefix_list,
- bgp_show_type_flap_prefix_longer,
- bgp_show_type_flap_route_map,
- bgp_show_type_flap_neighbor,
- bgp_show_type_dampend_paths,
- bgp_show_type_damp_neighbor
- };
- static int
- bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router_id,
- enum bgp_show_type type, void *output_arg)
- {
- struct bgp_info *ri;
- struct bgp_node *rn;
- int header = 1;
- int display;
- unsigned long output_count;
- /* This is first entry point, so reset total line. */
- output_count = 0;
- /* Start processing of routes. */
- for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
- if (rn->info != NULL)
- {
- display = 0;
- for (ri = rn->info; ri; ri = ri->next)
- {
- if (type == bgp_show_type_flap_statistics
- || type == bgp_show_type_flap_address
- || type == bgp_show_type_flap_prefix
- || type == bgp_show_type_flap_cidr_only
- || type == bgp_show_type_flap_regexp
- || type == bgp_show_type_flap_filter_list
- || type == bgp_show_type_flap_prefix_list
- || type == bgp_show_type_flap_prefix_longer
- || type == bgp_show_type_flap_route_map
- || type == bgp_show_type_flap_neighbor
- || type == bgp_show_type_dampend_paths
- || type == bgp_show_type_damp_neighbor)
- {
- if (!(ri->extra && ri->extra->damp_info))
- continue;
- }
- if (type == bgp_show_type_regexp
- || type == bgp_show_type_flap_regexp)
- {
- regex_t *regex = output_arg;
-
- if (bgp_regexec (regex, ri->attr->aspath) == REG_NOMATCH)
- continue;
- }
- if (type == bgp_show_type_prefix_list
- || type == bgp_show_type_flap_prefix_list)
- {
- struct prefix_list *plist = output_arg;
-
- if (prefix_list_apply (plist, &rn->p) != PREFIX_PERMIT)
- continue;
- }
- if (type == bgp_show_type_filter_list
- || type == bgp_show_type_flap_filter_list)
- {
- struct as_list *as_list = output_arg;
- if (as_list_apply (as_list, ri->attr->aspath) != AS_FILTER_PERMIT)
- continue;
- }
- if (type == bgp_show_type_route_map
- || type == bgp_show_type_flap_route_map)
- {
- struct route_map *rmap = output_arg;
- struct bgp_info binfo;
- struct attr dummy_attr;
- struct attr_extra dummy_extra;
- int ret;
- dummy_attr.extra = &dummy_extra;
- bgp_attr_dup (&dummy_attr, ri->attr);
- binfo.peer = ri->peer;
- binfo.attr = &dummy_attr;
- ret = route_map_apply (rmap, &rn->p, RMAP_BGP, &binfo);
- if (ret == RMAP_DENYMATCH)
- continue;
- }
- if (type == bgp_show_type_neighbor
- || type == bgp_show_type_flap_neighbor
- || type == bgp_show_type_damp_neighbor)
- {
- union sockunion *su = output_arg;
- if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su))
- continue;
- }
- if (type == bgp_show_type_cidr_only
- || type == bgp_show_type_flap_cidr_only)
- {
- u_int32_t destination;
- destination = ntohl (rn->p.u.prefix4.s_addr);
- if (IN_CLASSC (destination) && rn->p.prefixlen == 24)
- continue;
- if (IN_CLASSB (destination) && rn->p.prefixlen == 16)
- continue;
- if (IN_CLASSA (destination) && rn->p.prefixlen == 8)
- continue;
- }
- if (type == bgp_show_type_prefix_longer
- || type == bgp_show_type_flap_prefix_longer)
- {
- struct prefix *p = output_arg;
- if (! prefix_match (p, &rn->p))
- continue;
- }
- if (type == bgp_show_type_community_all)
- {
- if (! ri->attr->community)
- continue;
- }
- if (type == bgp_show_type_community)
- {
- struct community *com = output_arg;
- if (! ri->attr->community ||
- ! community_match (ri->attr->community, com))
- continue;
- }
- if (type == bgp_show_type_community_exact)
- {
- struct community *com = output_arg;
- if (! ri->attr->community ||
- ! community_cmp (ri->attr->community, com))
- continue;
- }
- if (type == bgp_show_type_community_list)
- {
- struct community_list *list = output_arg;
- if (! community_list_match (ri->attr->community, list))
- continue;
- }
- if (type == bgp_show_type_community_list_exact)
- {
- struct community_list *list = output_arg;
- if (! community_list_exact_match (ri->attr->community, list))
- continue;
- }
- if (type == bgp_show_type_flap_address
- || type == bgp_show_type_flap_prefix)
- {
- struct prefix *p = output_arg;
- if (! prefix_match (&rn->p, p))
- continue;
- if (type == bgp_show_type_flap_prefix)
- if (p->prefixlen != rn->p.prefixlen)
- continue;
- }
- if (type == bgp_show_type_dampend_paths
- || type == bgp_show_type_damp_neighbor)
- {
- if (! CHECK_FLAG (ri->flags, BGP_INFO_DAMPED)
- || CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
- continue;
- }
- if (header)
- {
- vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (*router_id), VTY_NEWLINE);
- vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
- vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
- if (type == bgp_show_type_dampend_paths
- || type == bgp_show_type_damp_neighbor)
- vty_out (vty, BGP_SHOW_DAMP_HEADER, VTY_NEWLINE);
- else if (type == bgp_show_type_flap_statistics
- || type == bgp_show_type_flap_address
- || type == bgp_show_type_flap_prefix
- || type == bgp_show_type_flap_cidr_only
- || type == bgp_show_type_flap_regexp
- || type == bgp_show_type_flap_filter_list
- || type == bgp_show_type_flap_prefix_list
- || type == bgp_show_type_flap_prefix_longer
- || type == bgp_show_type_flap_route_map
- || type == bgp_show_type_flap_neighbor)
- vty_out (vty, BGP_SHOW_FLAP_HEADER, VTY_NEWLINE);
- else
- vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
- header = 0;
- }
- if (type == bgp_show_type_dampend_paths
- || type == bgp_show_type_damp_neighbor)
- damp_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
- else if (type == bgp_show_type_flap_statistics
- || type == bgp_show_type_flap_address
- || type == bgp_show_type_flap_prefix
- || type == bgp_show_type_flap_cidr_only
- || type == bgp_show_type_flap_regexp
- || type == bgp_show_type_flap_filter_list
- || type == bgp_show_type_flap_prefix_list
- || type == bgp_show_type_flap_prefix_longer
- || type == bgp_show_type_flap_route_map
- || type == bgp_show_type_flap_neighbor)
- flap_route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
- else
- route_vty_out (vty, &rn->p, ri, display, SAFI_UNICAST);
- display++;
- }
- if (display)
- output_count++;
- }
- /* No route is displayed */
- if (output_count == 0)
- {
- if (type == bgp_show_type_normal)
- vty_out (vty, "No BGP network exists%s", VTY_NEWLINE);
- }
- else
- vty_out (vty, "%sTotal number of prefixes %ld%s",
- VTY_NEWLINE, output_count, VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- static int
- bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
- enum bgp_show_type type, void *output_arg)
- {
- struct bgp_table *table;
- if (bgp == NULL) {
- bgp = bgp_get_default ();
- }
- if (bgp == NULL)
- {
- vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- table = bgp->rib[afi][safi];
- return bgp_show_table (vty, table, &bgp->router_id, type, output_arg);
- }
- /* Header of detailed BGP route information */
- static void
- route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
- struct bgp_node *rn,
- struct prefix_rd *prd, afi_t afi, safi_t safi)
- {
- struct bgp_info *ri;
- struct prefix *p;
- struct peer *peer;
- struct listnode *node, *nnode;
- char buf1[INET6_ADDRSTRLEN];
- char buf2[INET6_ADDRSTRLEN];
- int count = 0;
- int best = 0;
- int suppress = 0;
- int no_export = 0;
- int no_advertise = 0;
- int local_as = 0;
- int first = 0;
- p = &rn->p;
- vty_out (vty, "BGP routing table entry for %s%s%s/%d%s",
- (safi == SAFI_MPLS_VPN ?
- prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""),
- safi == SAFI_MPLS_VPN ? ":" : "",
- inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN),
- p->prefixlen, VTY_NEWLINE);
- for (ri = rn->info; ri; ri = ri->next)
- {
- count++;
- if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED))
- {
- best = count;
- if (ri->extra && ri->extra->suppress)
- suppress = 1;
- if (ri->attr->community != NULL)
- {
- if (community_include (ri->attr->community, COMMUNITY_NO_ADVERTISE))
- no_advertise = 1;
- if (community_include (ri->attr->community, COMMUNITY_NO_EXPORT))
- no_export = 1;
- if (community_include (ri->attr->community, COMMUNITY_LOCAL_AS))
- local_as = 1;
- }
- }
- }
- vty_out (vty, "Paths: (%d available", count);
- if (best)
- {
- vty_out (vty, ", best #%d", best);
- if (safi == SAFI_UNICAST)
- vty_out (vty, ", table Default-IP-Routing-Table");
- }
- else
- vty_out (vty, ", no best path");
- if (no_advertise)
- vty_out (vty, ", not advertised to any peer");
- else if (no_export)
- vty_out (vty, ", not advertised to EBGP peer");
- else if (local_as)
- vty_out (vty, ", not advertised outside local AS");
- if (suppress)
- vty_out (vty, ", Advertisements suppressed by an aggregate.");
- vty_out (vty, ")%s", VTY_NEWLINE);
- /* advertised peer */
- for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
- {
- if (bgp_adj_out_lookup (peer, p, afi, safi, rn))
- {
- if (! first)
- vty_out (vty, " Advertised to non peer-group peers:%s ", VTY_NEWLINE);
- vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
- first = 1;
- }
- }
- if (! first)
- vty_out (vty, " Not advertised to any peer");
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- /* Display specified route of BGP table. */
- static int
- bgp_show_route_in_table (struct vty *vty, struct bgp *bgp,
- struct bgp_table *rib, const char *ip_str,
- afi_t afi, safi_t safi, struct prefix_rd *prd,
- int prefix_check)
- {
- int ret;
- int header;
- int display = 0;
- struct prefix match;
- struct bgp_node *rn;
- struct bgp_node *rm;
- struct bgp_info *ri;
- struct bgp_table *table;
- /* Check IP address argument. */
- ret = str2prefix (ip_str, &match);
- if (! ret)
- {
- vty_out (vty, "address is malformed%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- match.family = afi2family (afi);
- if (safi == SAFI_MPLS_VPN)
- {
- for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn))
- {
- if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
- continue;
- if ((table = rn->info) != NULL)
- {
- header = 1;
- if ((rm = bgp_node_match (table, &match)) != NULL)
- {
- if (prefix_check && rm->p.prefixlen != match.prefixlen)
- {
- bgp_unlock_node (rm);
- continue;
- }
- for (ri = rm->info; ri; ri = ri->next)
- {
- if (header)
- {
- route_vty_out_detail_header (vty, bgp, rm, (struct prefix_rd *)&rn->p,
- AFI_IP, SAFI_MPLS_VPN);
- header = 0;
- }
- display++;
- route_vty_out_detail (vty, bgp, &rm->p, ri, AFI_IP, SAFI_MPLS_VPN);
- }
- bgp_unlock_node (rm);
- }
- }
- }
- }
- else
- {
- header = 1;
- if ((rn = bgp_node_match (rib, &match)) != NULL)
- {
- if (! prefix_check || rn->p.prefixlen == match.prefixlen)
- {
- for (ri = rn->info; ri; ri = ri->next)
- {
- if (header)
- {
- route_vty_out_detail_header (vty, bgp, rn, NULL, afi, safi);
- header = 0;
- }
- display++;
- route_vty_out_detail (vty, bgp, &rn->p, ri, afi, safi);
- }
- }
- bgp_unlock_node (rn);
- }
- }
- if (! display)
- {
- vty_out (vty, "%% Network not in table%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return CMD_SUCCESS;
- }
- /* Display specified route of Main RIB */
- static int
- bgp_show_route (struct vty *vty, const char *view_name, const char *ip_str,
- afi_t afi, safi_t safi, struct prefix_rd *prd,
- int prefix_check)
- {
- struct bgp *bgp;
- /* BGP structure lookup. */
- if (view_name)
- {
- bgp = bgp_lookup_by_name (view_name);
- if (bgp == NULL)
- {
- vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
- else
- {
- bgp = bgp_get_default ();
- if (bgp == NULL)
- {
- vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
-
- return bgp_show_route_in_table (vty, bgp, bgp->rib[afi][safi], ip_str,
- afi, safi, prd, prefix_check);
- }
- /* BGP route print out function. */
- DEFUN (show_ip_bgp,
- show_ip_bgp_cmd,
- "show ip bgp",
- SHOW_STR
- IP_STR
- BGP_STR)
- {
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
- }
- DEFUN (show_ip_bgp_ipv4,
- show_ip_bgp_ipv4_cmd,
- "show ip bgp ipv4 (unicast|multicast)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST, bgp_show_type_normal,
- NULL);
-
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
- }
- ALIAS (show_ip_bgp_ipv4,
- show_bgp_ipv4_safi_cmd,
- "show bgp ipv4 (unicast|multicast)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n")
- DEFUN (show_ip_bgp_route,
- show_ip_bgp_route_cmd,
- "show ip bgp A.B.C.D",
- SHOW_STR
- IP_STR
- BGP_STR
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 0);
- }
- DEFUN (show_ip_bgp_ipv4_route,
- show_ip_bgp_ipv4_route_cmd,
- "show ip bgp ipv4 (unicast|multicast) A.B.C.D",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Network in the BGP routing table to display\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 0);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
- }
- ALIAS (show_ip_bgp_ipv4_route,
- show_bgp_ipv4_safi_route_cmd,
- "show bgp ipv4 (unicast|multicast) A.B.C.D",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Network in the BGP routing table to display\n")
- DEFUN (show_ip_bgp_vpnv4_all_route,
- show_ip_bgp_vpnv4_all_route_cmd,
- "show ip bgp vpnv4 all A.B.C.D",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display VPNv4 NLRI specific information\n"
- "Display information about all VPNv4 NLRIs\n"
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 0);
- }
- DEFUN (show_ip_bgp_vpnv4_rd_route,
- show_ip_bgp_vpnv4_rd_route_cmd,
- "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display VPNv4 NLRI specific information\n"
- "Display information for a route distinguisher\n"
- "VPN Route Distinguisher\n"
- "Network in the BGP routing table to display\n")
- {
- int ret;
- struct prefix_rd prd;
- ret = str2prefix_rd (argv[0], &prd);
- if (! ret)
- {
- vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 0);
- }
- DEFUN (show_ip_bgp_prefix,
- show_ip_bgp_prefix_cmd,
- "show ip bgp A.B.C.D/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_UNICAST, NULL, 1);
- }
- DEFUN (show_ip_bgp_ipv4_prefix,
- show_ip_bgp_ipv4_prefix_cmd,
- "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MULTICAST, NULL, 1);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
- }
- ALIAS (show_ip_bgp_ipv4_prefix,
- show_bgp_ipv4_safi_prefix_cmd,
- "show bgp ipv4 (unicast|multicast) A.B.C.D/M",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- DEFUN (show_ip_bgp_vpnv4_all_prefix,
- show_ip_bgp_vpnv4_all_prefix_cmd,
- "show ip bgp vpnv4 all A.B.C.D/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display VPNv4 NLRI specific information\n"
- "Display information about all VPNv4 NLRIs\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP, SAFI_MPLS_VPN, NULL, 1);
- }
- DEFUN (show_ip_bgp_vpnv4_rd_prefix,
- show_ip_bgp_vpnv4_rd_prefix_cmd,
- "show ip bgp vpnv4 rd ASN:nn_or_IP-address:nn A.B.C.D/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display VPNv4 NLRI specific information\n"
- "Display information for a route distinguisher\n"
- "VPN Route Distinguisher\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- int ret;
- struct prefix_rd prd;
- ret = str2prefix_rd (argv[0], &prd);
- if (! ret)
- {
- vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show_route (vty, NULL, argv[1], AFI_IP, SAFI_MPLS_VPN, &prd, 1);
- }
- DEFUN (show_ip_bgp_view,
- show_ip_bgp_view_cmd,
- "show ip bgp view WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n")
- {
- struct bgp *bgp;
- /* BGP structure lookup. */
- bgp = bgp_lookup_by_name (argv[0]);
- if (bgp == NULL)
- {
- vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show (vty, bgp, AFI_IP, SAFI_UNICAST, bgp_show_type_normal, NULL);
- }
- DEFUN (show_ip_bgp_view_route,
- show_ip_bgp_view_route_cmd,
- "show ip bgp view WORD A.B.C.D",
- SHOW_STR
- IP_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 0);
- }
- DEFUN (show_ip_bgp_view_prefix,
- show_ip_bgp_view_prefix_cmd,
- "show ip bgp view WORD A.B.C.D/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP, SAFI_UNICAST, NULL, 1);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp,
- show_bgp_cmd,
- "show bgp",
- SHOW_STR
- BGP_STR)
- {
- return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal,
- NULL);
- }
- ALIAS (show_bgp,
- show_bgp_ipv6_cmd,
- "show bgp ipv6",
- SHOW_STR
- BGP_STR
- "Address family\n")
- DEFUN (show_bgp_ipv6_safi,
- show_bgp_ipv6_safi_cmd,
- "show bgp ipv6 (unicast|multicast)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal,
- NULL);
- return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL);
- }
- /* old command */
- DEFUN (show_ipv6_bgp,
- show_ipv6_bgp_cmd,
- "show ipv6 bgp",
- SHOW_STR
- IP_STR
- BGP_STR)
- {
- return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal,
- NULL);
- }
- DEFUN (show_bgp_route,
- show_bgp_route_cmd,
- "show bgp X:X::X:X",
- SHOW_STR
- BGP_STR
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
- }
- ALIAS (show_bgp_route,
- show_bgp_ipv6_route_cmd,
- "show bgp ipv6 X:X::X:X",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Network in the BGP routing table to display\n")
- DEFUN (show_bgp_ipv6_safi_route,
- show_bgp_ipv6_safi_route_cmd,
- "show bgp ipv6 (unicast|multicast) X:X::X:X",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Network in the BGP routing table to display\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 0);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
- }
- /* old command */
- DEFUN (show_ipv6_bgp_route,
- show_ipv6_bgp_route_cmd,
- "show ipv6 bgp X:X::X:X",
- SHOW_STR
- IP_STR
- BGP_STR
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 0);
- }
- DEFUN (show_bgp_prefix,
- show_bgp_prefix_cmd,
- "show bgp X:X::X:X/M",
- SHOW_STR
- BGP_STR
- "IPv6 prefix <network>/<length>\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
- }
- ALIAS (show_bgp_prefix,
- show_bgp_ipv6_prefix_cmd,
- "show bgp ipv6 X:X::X:X/M",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "IPv6 prefix <network>/<length>\n")
- DEFUN (show_bgp_ipv6_safi_prefix,
- show_bgp_ipv6_safi_prefix_cmd,
- "show bgp ipv6 (unicast|multicast) X:X::X:X/M",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_MULTICAST, NULL, 1);
- return bgp_show_route (vty, NULL, argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
- }
- /* old command */
- DEFUN (show_ipv6_bgp_prefix,
- show_ipv6_bgp_prefix_cmd,
- "show ipv6 bgp X:X::X:X/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_UNICAST, NULL, 1);
- }
- DEFUN (show_bgp_view,
- show_bgp_view_cmd,
- "show bgp view WORD",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "View name\n")
- {
- struct bgp *bgp;
- /* BGP structure lookup. */
- bgp = bgp_lookup_by_name (argv[0]);
- if (bgp == NULL)
- {
- vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- return bgp_show (vty, bgp, AFI_IP6, SAFI_UNICAST, bgp_show_type_normal, NULL);
- }
- ALIAS (show_bgp_view,
- show_bgp_view_ipv6_cmd,
- "show bgp view WORD ipv6",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "View name\n"
- "Address family\n")
-
- DEFUN (show_bgp_view_route,
- show_bgp_view_route_cmd,
- "show bgp view WORD X:X::X:X",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "View name\n"
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 0);
- }
- ALIAS (show_bgp_view_route,
- show_bgp_view_ipv6_route_cmd,
- "show bgp view WORD ipv6 X:X::X:X",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "View name\n"
- "Address family\n"
- "Network in the BGP routing table to display\n")
- DEFUN (show_bgp_view_prefix,
- show_bgp_view_prefix_cmd,
- "show bgp view WORD X:X::X:X/M",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "View name\n"
- "IPv6 prefix <network>/<length>\n")
- {
- return bgp_show_route (vty, argv[0], argv[1], AFI_IP6, SAFI_UNICAST, NULL, 1);
- }
- ALIAS (show_bgp_view_prefix,
- show_bgp_view_ipv6_prefix_cmd,
- "show bgp view WORD ipv6 X:X::X:X/M",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "View name\n"
- "Address family\n"
- "IPv6 prefix <network>/<length>\n")
- /* old command */
- DEFUN (show_ipv6_mbgp,
- show_ipv6_mbgp_cmd,
- "show ipv6 mbgp",
- SHOW_STR
- IP_STR
- MBGP_STR)
- {
- return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST, bgp_show_type_normal,
- NULL);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_route,
- show_ipv6_mbgp_route_cmd,
- "show ipv6 mbgp X:X::X:X",
- SHOW_STR
- IP_STR
- MBGP_STR
- "Network in the MBGP routing table to display\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 0);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_prefix,
- show_ipv6_mbgp_prefix_cmd,
- "show ipv6 mbgp X:X::X:X/M",
- SHOW_STR
- IP_STR
- MBGP_STR
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n")
- {
- return bgp_show_route (vty, NULL, argv[0], AFI_IP6, SAFI_MULTICAST, NULL, 1);
- }
- #endif
- static int
- bgp_show_regexp (struct vty *vty, int argc, const char **argv, afi_t afi,
- safi_t safi, enum bgp_show_type type)
- {
- int i;
- struct buffer *b;
- char *regstr;
- int first;
- regex_t *regex;
- int rc;
-
- first = 0;
- b = buffer_new (1024);
- for (i = 0; i < argc; i++)
- {
- if (first)
- buffer_putc (b, ' ');
- else
- {
- if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0))
- continue;
- first = 1;
- }
- buffer_putstr (b, argv[i]);
- }
- buffer_putc (b, '\0');
- regstr = buffer_getstr (b);
- buffer_free (b);
- regex = bgp_regcomp (regstr);
- XFREE(MTYPE_TMP, regstr);
- if (! regex)
- {
- vty_out (vty, "Can't compile regexp %s%s", argv[0],
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- rc = bgp_show (vty, NULL, afi, safi, type, regex);
- bgp_regex_free (regex);
- return rc;
- }
- DEFUN (show_ip_bgp_regexp,
- show_ip_bgp_regexp_cmd,
- "show ip bgp regexp .LINE",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
- {
- return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST,
- bgp_show_type_regexp);
- }
- DEFUN (show_ip_bgp_flap_regexp,
- show_ip_bgp_flap_regexp_cmd,
- "show ip bgp flap-statistics regexp .LINE",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
- {
- return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_regexp);
- }
- DEFUN (show_ip_bgp_ipv4_regexp,
- show_ip_bgp_ipv4_regexp_cmd,
- "show ip bgp ipv4 (unicast|multicast) regexp .LINE",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_MULTICAST,
- bgp_show_type_regexp);
- return bgp_show_regexp (vty, argc, argv, AFI_IP, SAFI_UNICAST,
- bgp_show_type_regexp);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_regexp,
- show_bgp_regexp_cmd,
- "show bgp regexp .LINE",
- SHOW_STR
- BGP_STR
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
- {
- return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_UNICAST,
- bgp_show_type_regexp);
- }
- ALIAS (show_bgp_regexp,
- show_bgp_ipv6_regexp_cmd,
- "show bgp ipv6 regexp .LINE",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
- /* old command */
- DEFUN (show_ipv6_bgp_regexp,
- show_ipv6_bgp_regexp_cmd,
- "show ipv6 bgp regexp .LINE",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the BGP AS paths\n")
- {
- return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_UNICAST,
- bgp_show_type_regexp);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_regexp,
- show_ipv6_mbgp_regexp_cmd,
- "show ipv6 mbgp regexp .LINE",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the AS path regular expression\n"
- "A regular-expression to match the MBGP AS paths\n")
- {
- return bgp_show_regexp (vty, argc, argv, AFI_IP6, SAFI_MULTICAST,
- bgp_show_type_regexp);
- }
- #endif /* HAVE_IPV6 */
- static int
- bgp_show_prefix_list (struct vty *vty, const char *prefix_list_str, afi_t afi,
- safi_t safi, enum bgp_show_type type)
- {
- struct prefix_list *plist;
- plist = prefix_list_lookup (afi, prefix_list_str);
- if (plist == NULL)
- {
- vty_out (vty, "%% %s is not a valid prefix-list name%s",
- prefix_list_str, VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show (vty, NULL, afi, safi, type, plist);
- }
- DEFUN (show_ip_bgp_prefix_list,
- show_ip_bgp_prefix_list_cmd,
- "show ip bgp prefix-list WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes conforming to the prefix-list\n"
- "IP prefix-list name\n")
- {
- return bgp_show_prefix_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_prefix_list);
- }
- DEFUN (show_ip_bgp_flap_prefix_list,
- show_ip_bgp_flap_prefix_list_cmd,
- "show ip bgp flap-statistics prefix-list WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "Display routes conforming to the prefix-list\n"
- "IP prefix-list name\n")
- {
- return bgp_show_prefix_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_prefix_list);
- }
- DEFUN (show_ip_bgp_ipv4_prefix_list,
- show_ip_bgp_ipv4_prefix_list_cmd,
- "show ip bgp ipv4 (unicast|multicast) prefix-list WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes conforming to the prefix-list\n"
- "IP prefix-list name\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_prefix_list (vty, argv[1], AFI_IP, SAFI_MULTICAST,
- bgp_show_type_prefix_list);
- return bgp_show_prefix_list (vty, argv[1], AFI_IP, SAFI_UNICAST,
- bgp_show_type_prefix_list);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_prefix_list,
- show_bgp_prefix_list_cmd,
- "show bgp prefix-list WORD",
- SHOW_STR
- BGP_STR
- "Display routes conforming to the prefix-list\n"
- "IPv6 prefix-list name\n")
- {
- return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_prefix_list);
- }
- ALIAS (show_bgp_prefix_list,
- show_bgp_ipv6_prefix_list_cmd,
- "show bgp ipv6 prefix-list WORD",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes conforming to the prefix-list\n"
- "IPv6 prefix-list name\n")
- /* old command */
- DEFUN (show_ipv6_bgp_prefix_list,
- show_ipv6_bgp_prefix_list_cmd,
- "show ipv6 bgp prefix-list WORD",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the prefix-list\n"
- "IPv6 prefix-list name\n")
- {
- return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_prefix_list);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_prefix_list,
- show_ipv6_mbgp_prefix_list_cmd,
- "show ipv6 mbgp prefix-list WORD",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the prefix-list\n"
- "IPv6 prefix-list name\n")
- {
- return bgp_show_prefix_list (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
- bgp_show_type_prefix_list);
- }
- #endif /* HAVE_IPV6 */
- static int
- bgp_show_filter_list (struct vty *vty, const char *filter, afi_t afi,
- safi_t safi, enum bgp_show_type type)
- {
- struct as_list *as_list;
- as_list = as_list_lookup (filter);
- if (as_list == NULL)
- {
- vty_out (vty, "%% %s is not a valid AS-path access-list name%s", filter, VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show (vty, NULL, afi, safi, type, as_list);
- }
- DEFUN (show_ip_bgp_filter_list,
- show_ip_bgp_filter_list_cmd,
- "show ip bgp filter-list WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- {
- return bgp_show_filter_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_filter_list);
- }
- DEFUN (show_ip_bgp_flap_filter_list,
- show_ip_bgp_flap_filter_list_cmd,
- "show ip bgp flap-statistics filter-list WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- {
- return bgp_show_filter_list (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_filter_list);
- }
- DEFUN (show_ip_bgp_ipv4_filter_list,
- show_ip_bgp_ipv4_filter_list_cmd,
- "show ip bgp ipv4 (unicast|multicast) filter-list WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_MULTICAST,
- bgp_show_type_filter_list);
-
- return bgp_show_filter_list (vty, argv[1], AFI_IP, SAFI_UNICAST,
- bgp_show_type_filter_list);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_filter_list,
- show_bgp_filter_list_cmd,
- "show bgp filter-list WORD",
- SHOW_STR
- BGP_STR
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- {
- return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_filter_list);
- }
- ALIAS (show_bgp_filter_list,
- show_bgp_ipv6_filter_list_cmd,
- "show bgp ipv6 filter-list WORD",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- /* old command */
- DEFUN (show_ipv6_bgp_filter_list,
- show_ipv6_bgp_filter_list_cmd,
- "show ipv6 bgp filter-list WORD",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- {
- return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_filter_list);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_filter_list,
- show_ipv6_mbgp_filter_list_cmd,
- "show ipv6 mbgp filter-list WORD",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n")
- {
- return bgp_show_filter_list (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
- bgp_show_type_filter_list);
- }
- #endif /* HAVE_IPV6 */
- static int
- bgp_show_route_map (struct vty *vty, const char *rmap_str, afi_t afi,
- safi_t safi, enum bgp_show_type type)
- {
- struct route_map *rmap;
- rmap = route_map_lookup_by_name (rmap_str);
- if (! rmap)
- {
- vty_out (vty, "%% %s is not a valid route-map name%s",
- rmap_str, VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show (vty, NULL, afi, safi, type, rmap);
- }
- DEFUN (show_ip_bgp_route_map,
- show_ip_bgp_route_map_cmd,
- "show ip bgp route-map WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the route-map\n"
- "A route-map to match on\n")
- {
- return bgp_show_route_map (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_route_map);
- }
- DEFUN (show_ip_bgp_flap_route_map,
- show_ip_bgp_flap_route_map_cmd,
- "show ip bgp flap-statistics route-map WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "Display routes matching the route-map\n"
- "A route-map to match on\n")
- {
- return bgp_show_route_map (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_route_map);
- }
- DEFUN (show_ip_bgp_ipv4_route_map,
- show_ip_bgp_ipv4_route_map_cmd,
- "show ip bgp ipv4 (unicast|multicast) route-map WORD",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the route-map\n"
- "A route-map to match on\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_route_map (vty, argv[1], AFI_IP, SAFI_MULTICAST,
- bgp_show_type_route_map);
- return bgp_show_route_map (vty, argv[1], AFI_IP, SAFI_UNICAST,
- bgp_show_type_route_map);
- }
- DEFUN (show_bgp_route_map,
- show_bgp_route_map_cmd,
- "show bgp route-map WORD",
- SHOW_STR
- BGP_STR
- "Display routes matching the route-map\n"
- "A route-map to match on\n")
- {
- return bgp_show_route_map (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_route_map);
- }
- ALIAS (show_bgp_route_map,
- show_bgp_ipv6_route_map_cmd,
- "show bgp ipv6 route-map WORD",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the route-map\n"
- "A route-map to match on\n")
- DEFUN (show_ip_bgp_cidr_only,
- show_ip_bgp_cidr_only_cmd,
- "show ip bgp cidr-only",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display only routes with non-natural netmasks\n")
- {
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
- bgp_show_type_cidr_only, NULL);
- }
- DEFUN (show_ip_bgp_flap_cidr_only,
- show_ip_bgp_flap_cidr_only_cmd,
- "show ip bgp flap-statistics cidr-only",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "Display only routes with non-natural netmasks\n")
- {
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_cidr_only, NULL);
- }
- DEFUN (show_ip_bgp_ipv4_cidr_only,
- show_ip_bgp_ipv4_cidr_only_cmd,
- "show ip bgp ipv4 (unicast|multicast) cidr-only",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display only routes with non-natural netmasks\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
- bgp_show_type_cidr_only, NULL);
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
- bgp_show_type_cidr_only, NULL);
- }
- DEFUN (show_ip_bgp_community_all,
- show_ip_bgp_community_all_cmd,
- "show ip bgp community",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n")
- {
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
- bgp_show_type_community_all, NULL);
- }
- DEFUN (show_ip_bgp_ipv4_community_all,
- show_ip_bgp_ipv4_community_all_cmd,
- "show ip bgp ipv4 (unicast|multicast) community",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show (vty, NULL, AFI_IP, SAFI_MULTICAST,
- bgp_show_type_community_all, NULL);
-
- return bgp_show (vty, NULL, AFI_IP, SAFI_UNICAST,
- bgp_show_type_community_all, NULL);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_community_all,
- show_bgp_community_all_cmd,
- "show bgp community",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n")
- {
- return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST,
- bgp_show_type_community_all, NULL);
- }
- ALIAS (show_bgp_community_all,
- show_bgp_ipv6_community_all_cmd,
- "show bgp ipv6 community",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n")
- /* old command */
- DEFUN (show_ipv6_bgp_community_all,
- show_ipv6_bgp_community_all_cmd,
- "show ipv6 bgp community",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n")
- {
- return bgp_show (vty, NULL, AFI_IP6, SAFI_UNICAST,
- bgp_show_type_community_all, NULL);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_community_all,
- show_ipv6_mbgp_community_all_cmd,
- "show ipv6 mbgp community",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n")
- {
- return bgp_show (vty, NULL, AFI_IP6, SAFI_MULTICAST,
- bgp_show_type_community_all, NULL);
- }
- #endif /* HAVE_IPV6 */
- static int
- bgp_show_community (struct vty *vty, const char *view_name, int argc,
- const char **argv, int exact, afi_t afi, safi_t safi)
- {
- struct community *com;
- struct buffer *b;
- struct bgp *bgp;
- int i;
- char *str;
- int first = 0;
- /* BGP structure lookup */
- if (view_name)
- {
- bgp = bgp_lookup_by_name (view_name);
- if (bgp == NULL)
- {
- vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
- else
- {
- bgp = bgp_get_default ();
- if (bgp == NULL)
- {
- vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
- b = buffer_new (1024);
- for (i = 0; i < argc; i++)
- {
- if (first)
- buffer_putc (b, ' ');
- else
- {
- if ((strcmp (argv[i], "unicast") == 0) || (strcmp (argv[i], "multicast") == 0))
- continue;
- first = 1;
- }
-
- buffer_putstr (b, argv[i]);
- }
- buffer_putc (b, '\0');
- str = buffer_getstr (b);
- buffer_free (b);
- com = community_str2com (str);
- XFREE (MTYPE_TMP, str);
- if (! com)
- {
- vty_out (vty, "%% Community malformed: %s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show (vty, bgp, afi, safi,
- (exact ? bgp_show_type_community_exact :
- bgp_show_type_community), com);
- }
- DEFUN (show_ip_bgp_community,
- show_ip_bgp_community_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- {
- return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
- }
- ALIAS (show_ip_bgp_community,
- show_ip_bgp_community2_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
-
- ALIAS (show_ip_bgp_community,
- show_ip_bgp_community3_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
-
- ALIAS (show_ip_bgp_community,
- show_ip_bgp_community4_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- DEFUN (show_ip_bgp_ipv4_community,
- show_ip_bgp_ipv4_community_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_MULTICAST);
-
- return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP, SAFI_UNICAST);
- }
- ALIAS (show_ip_bgp_ipv4_community,
- show_ip_bgp_ipv4_community2_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
-
- ALIAS (show_ip_bgp_ipv4_community,
- show_ip_bgp_ipv4_community3_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
-
- ALIAS (show_ip_bgp_ipv4_community,
- show_ip_bgp_ipv4_community4_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- DEFUN (show_bgp_view_afi_safi_community_all,
- show_bgp_view_afi_safi_community_all_cmd,
- #ifdef HAVE_IPV6
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community",
- #else
- "show bgp view WORD ipv4 (unicast|multicast) community",
- #endif
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "Address family\n"
- #ifdef HAVE_IPV6
- "Address family\n"
- #endif
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes containing communities\n")
- {
- int afi;
- int safi;
- struct bgp *bgp;
- /* BGP structure lookup. */
- bgp = bgp_lookup_by_name (argv[0]);
- if (bgp == NULL)
- {
- vty_out (vty, "Can't find BGP view %s%s", argv[0], VTY_NEWLINE);
- return CMD_WARNING;
- }
- #ifdef HAVE_IPV6
- afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
- safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
- #else
- afi = AFI_IP;
- safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
- #endif
- return bgp_show (vty, bgp, afi, safi, bgp_show_type_community_all, NULL);
- }
- DEFUN (show_bgp_view_afi_safi_community,
- show_bgp_view_afi_safi_community_cmd,
- #ifdef HAVE_IPV6
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
- #else
- "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export)",
- #endif
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "Address family\n"
- #ifdef HAVE_IPV6
- "Address family\n"
- #endif
- "Address family modifier\n"
- "Address family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- {
- int afi;
- int safi;
- #ifdef HAVE_IPV6
- afi = (strncmp (argv[1], "ipv6", 4) == 0) ? AFI_IP6 : AFI_IP;
- safi = (strncmp (argv[2], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
- return bgp_show_community (vty, argv[0], argc-3, &argv[3], 0, afi, safi);
- #else
- afi = AFI_IP;
- safi = (strncmp (argv[1], "m", 1) == 0) ? SAFI_MULTICAST : SAFI_UNICAST;
- return bgp_show_community (vty, argv[0], argc-2, &argv[2], 0, afi, safi);
- #endif
- }
- ALIAS (show_bgp_view_afi_safi_community,
- show_bgp_view_afi_safi_community2_cmd,
- #ifdef HAVE_IPV6
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- #else
- "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- #endif
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "Address family\n"
- #ifdef HAVE_IPV6
- "Address family\n"
- #endif
- "Address family modifier\n"
- "Address family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_view_afi_safi_community,
- show_bgp_view_afi_safi_community3_cmd,
- #ifdef HAVE_IPV6
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- #else
- "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- #endif
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "Address family\n"
- #ifdef HAVE_IPV6
- "Address family\n"
- #endif
- "Address family modifier\n"
- "Address family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_view_afi_safi_community,
- show_bgp_view_afi_safi_community4_cmd,
- #ifdef HAVE_IPV6
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- #else
- "show bgp view WORD ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- #endif
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "BGP view name\n"
- "Address family\n"
- #ifdef HAVE_IPV6
- "Address family\n"
- #endif
- "Address family modifier\n"
- "Address family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- DEFUN (show_ip_bgp_community_exact,
- show_ip_bgp_community_exact_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- {
- return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
- }
- ALIAS (show_ip_bgp_community_exact,
- show_ip_bgp_community2_exact_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_ip_bgp_community_exact,
- show_ip_bgp_community3_exact_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_ip_bgp_community_exact,
- show_ip_bgp_community4_exact_cmd,
- "show ip bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- DEFUN (show_ip_bgp_ipv4_community_exact,
- show_ip_bgp_ipv4_community_exact_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_MULTICAST);
-
- return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP, SAFI_UNICAST);
- }
- ALIAS (show_ip_bgp_ipv4_community_exact,
- show_ip_bgp_ipv4_community2_exact_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_ip_bgp_ipv4_community_exact,
- show_ip_bgp_ipv4_community3_exact_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
-
- ALIAS (show_ip_bgp_ipv4_community_exact,
- show_ip_bgp_ipv4_community4_exact_cmd,
- "show ip bgp ipv4 (unicast|multicast) community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_community,
- show_bgp_community_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- {
- return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
- }
- ALIAS (show_bgp_community,
- show_bgp_ipv6_community_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_community,
- show_bgp_community2_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_community,
- show_bgp_ipv6_community2_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
-
- ALIAS (show_bgp_community,
- show_bgp_community3_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_community,
- show_bgp_ipv6_community3_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_community,
- show_bgp_community4_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- ALIAS (show_bgp_community,
- show_bgp_ipv6_community4_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- /* old command */
- DEFUN (show_ipv6_bgp_community,
- show_ipv6_bgp_community_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- {
- return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_UNICAST);
- }
- /* old command */
- ALIAS (show_ipv6_bgp_community,
- show_ipv6_bgp_community2_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- /* old command */
- ALIAS (show_ipv6_bgp_community,
- show_ipv6_bgp_community3_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- /* old command */
- ALIAS (show_ipv6_bgp_community,
- show_ipv6_bgp_community4_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- DEFUN (show_bgp_community_exact,
- show_bgp_community_exact_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- {
- return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
- }
- ALIAS (show_bgp_community_exact,
- show_bgp_ipv6_community_exact_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_bgp_community_exact,
- show_bgp_community2_exact_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_bgp_community_exact,
- show_bgp_ipv6_community2_exact_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_bgp_community_exact,
- show_bgp_community3_exact_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_bgp_community_exact,
- show_bgp_ipv6_community3_exact_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- ALIAS (show_bgp_community_exact,
- show_bgp_community4_exact_cmd,
- "show bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
-
- ALIAS (show_bgp_community_exact,
- show_bgp_ipv6_community4_exact_cmd,
- "show bgp ipv6 community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- /* old command */
- DEFUN (show_ipv6_bgp_community_exact,
- show_ipv6_bgp_community_exact_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- {
- return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_UNICAST);
- }
- /* old command */
- ALIAS (show_ipv6_bgp_community_exact,
- show_ipv6_bgp_community2_exact_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- /* old command */
- ALIAS (show_ipv6_bgp_community_exact,
- show_ipv6_bgp_community3_exact_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- /* old command */
- ALIAS (show_ipv6_bgp_community_exact,
- show_ipv6_bgp_community4_exact_cmd,
- "show ipv6 bgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
-
- /* old command */
- DEFUN (show_ipv6_mbgp_community,
- show_ipv6_mbgp_community_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- {
- return bgp_show_community (vty, NULL, argc, argv, 0, AFI_IP6, SAFI_MULTICAST);
- }
- /* old command */
- ALIAS (show_ipv6_mbgp_community,
- show_ipv6_mbgp_community2_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- /* old command */
- ALIAS (show_ipv6_mbgp_community,
- show_ipv6_mbgp_community3_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- /* old command */
- ALIAS (show_ipv6_mbgp_community,
- show_ipv6_mbgp_community4_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export)",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n")
- /* old command */
- DEFUN (show_ipv6_mbgp_community_exact,
- show_ipv6_mbgp_community_exact_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- {
- return bgp_show_community (vty, NULL, argc, argv, 1, AFI_IP6, SAFI_MULTICAST);
- }
- /* old command */
- ALIAS (show_ipv6_mbgp_community_exact,
- show_ipv6_mbgp_community2_exact_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- /* old command */
- ALIAS (show_ipv6_mbgp_community_exact,
- show_ipv6_mbgp_community3_exact_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- /* old command */
- ALIAS (show_ipv6_mbgp_community_exact,
- show_ipv6_mbgp_community4_exact_cmd,
- "show ipv6 mbgp community (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) (AA:NN|local-AS|no-advertise|no-export) exact-match",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the communities\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "community number\n"
- "Do not send outside local AS (well-known community)\n"
- "Do not advertise to any peer (well-known community)\n"
- "Do not export to next AS (well-known community)\n"
- "Exact match of the communities")
- #endif /* HAVE_IPV6 */
- static int
- bgp_show_community_list (struct vty *vty, const char *com, int exact,
- afi_t afi, safi_t safi)
- {
- struct community_list *list;
- list = community_list_lookup (bgp_clist, com, COMMUNITY_LIST_MASTER);
- if (list == NULL)
- {
- vty_out (vty, "%% %s is not a valid community-list name%s", com,
- VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_show (vty, NULL, afi, safi,
- (exact ? bgp_show_type_community_list_exact :
- bgp_show_type_community_list), list);
- }
- DEFUN (show_ip_bgp_community_list,
- show_ip_bgp_community_list_cmd,
- "show ip bgp community-list (<1-500>|WORD)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n")
- {
- return bgp_show_community_list (vty, argv[0], 0, AFI_IP, SAFI_UNICAST);
- }
- DEFUN (show_ip_bgp_ipv4_community_list,
- show_ip_bgp_ipv4_community_list_cmd,
- "show ip bgp ipv4 (unicast|multicast) community-list (<1-500>|WORD)",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_MULTICAST);
-
- return bgp_show_community_list (vty, argv[1], 0, AFI_IP, SAFI_UNICAST);
- }
- DEFUN (show_ip_bgp_community_list_exact,
- show_ip_bgp_community_list_exact_cmd,
- "show ip bgp community-list (<1-500>|WORD) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n"
- "Exact match of the communities\n")
- {
- return bgp_show_community_list (vty, argv[0], 1, AFI_IP, SAFI_UNICAST);
- }
- DEFUN (show_ip_bgp_ipv4_community_list_exact,
- show_ip_bgp_ipv4_community_list_exact_cmd,
- "show ip bgp ipv4 (unicast|multicast) community-list (<1-500>|WORD) exact-match",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n"
- "Exact match of the communities\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_MULTICAST);
-
- return bgp_show_community_list (vty, argv[1], 1, AFI_IP, SAFI_UNICAST);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_community_list,
- show_bgp_community_list_cmd,
- "show bgp community-list (<1-500>|WORD)",
- SHOW_STR
- BGP_STR
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n")
- {
- return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_UNICAST);
- }
- ALIAS (show_bgp_community_list,
- show_bgp_ipv6_community_list_cmd,
- "show bgp ipv6 community-list (<1-500>|WORD)",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n")
- /* old command */
- DEFUN (show_ipv6_bgp_community_list,
- show_ipv6_bgp_community_list_cmd,
- "show ipv6 bgp community-list WORD",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the community-list\n"
- "community-list name\n")
- {
- return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_UNICAST);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_community_list,
- show_ipv6_mbgp_community_list_cmd,
- "show ipv6 mbgp community-list WORD",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the community-list\n"
- "community-list name\n")
- {
- return bgp_show_community_list (vty, argv[0], 0, AFI_IP6, SAFI_MULTICAST);
- }
- DEFUN (show_bgp_community_list_exact,
- show_bgp_community_list_exact_cmd,
- "show bgp community-list (<1-500>|WORD) exact-match",
- SHOW_STR
- BGP_STR
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n"
- "Exact match of the communities\n")
- {
- return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_UNICAST);
- }
- ALIAS (show_bgp_community_list_exact,
- show_bgp_ipv6_community_list_exact_cmd,
- "show bgp ipv6 community-list (<1-500>|WORD) exact-match",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n"
- "Exact match of the communities\n")
- /* old command */
- DEFUN (show_ipv6_bgp_community_list_exact,
- show_ipv6_bgp_community_list_exact_cmd,
- "show ipv6 bgp community-list WORD exact-match",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "Display routes matching the community-list\n"
- "community-list name\n"
- "Exact match of the communities\n")
- {
- return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_UNICAST);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_community_list_exact,
- show_ipv6_mbgp_community_list_exact_cmd,
- "show ipv6 mbgp community-list WORD exact-match",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "Display routes matching the community-list\n"
- "community-list name\n"
- "Exact match of the communities\n")
- {
- return bgp_show_community_list (vty, argv[0], 1, AFI_IP6, SAFI_MULTICAST);
- }
- #endif /* HAVE_IPV6 */
- static int
- bgp_show_prefix_longer (struct vty *vty, const char *prefix, afi_t afi,
- safi_t safi, enum bgp_show_type type)
- {
- int ret;
- struct prefix *p;
- p = prefix_new();
- ret = str2prefix (prefix, p);
- if (! ret)
- {
- vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- ret = bgp_show (vty, NULL, afi, safi, type, p);
- prefix_free(p);
- return ret;
- }
- DEFUN (show_ip_bgp_prefix_longer,
- show_ip_bgp_prefix_longer_cmd,
- "show ip bgp A.B.C.D/M longer-prefixes",
- SHOW_STR
- IP_STR
- BGP_STR
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Display route and more specific routes\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_prefix_longer);
- }
- DEFUN (show_ip_bgp_flap_prefix_longer,
- show_ip_bgp_flap_prefix_longer_cmd,
- "show ip bgp flap-statistics A.B.C.D/M longer-prefixes",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Display route and more specific routes\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_prefix_longer);
- }
- DEFUN (show_ip_bgp_ipv4_prefix_longer,
- show_ip_bgp_ipv4_prefix_longer_cmd,
- "show ip bgp ipv4 (unicast|multicast) A.B.C.D/M longer-prefixes",
- SHOW_STR
- IP_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
- "Display route and more specific routes\n")
- {
- if (strncmp (argv[0], "m", 1) == 0)
- return bgp_show_prefix_longer (vty, argv[1], AFI_IP, SAFI_MULTICAST,
- bgp_show_type_prefix_longer);
- return bgp_show_prefix_longer (vty, argv[1], AFI_IP, SAFI_UNICAST,
- bgp_show_type_prefix_longer);
- }
- DEFUN (show_ip_bgp_flap_address,
- show_ip_bgp_flap_address_cmd,
- "show ip bgp flap-statistics A.B.C.D",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "Network in the BGP routing table to display\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_address);
- }
- DEFUN (show_ip_bgp_flap_prefix,
- show_ip_bgp_flap_prefix_cmd,
- "show ip bgp flap-statistics A.B.C.D/M",
- SHOW_STR
- IP_STR
- BGP_STR
- "Display flap statistics of routes\n"
- "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP, SAFI_UNICAST,
- bgp_show_type_flap_prefix);
- }
- #ifdef HAVE_IPV6
- DEFUN (show_bgp_prefix_longer,
- show_bgp_prefix_longer_cmd,
- "show bgp X:X::X:X/M longer-prefixes",
- SHOW_STR
- BGP_STR
- "IPv6 prefix <network>/<length>\n"
- "Display route and more specific routes\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_prefix_longer);
- }
- ALIAS (show_bgp_prefix_longer,
- show_bgp_ipv6_prefix_longer_cmd,
- "show bgp ipv6 X:X::X:X/M longer-prefixes",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "IPv6 prefix <network>/<length>\n"
- "Display route and more specific routes\n")
- /* old command */
- DEFUN (show_ipv6_bgp_prefix_longer,
- show_ipv6_bgp_prefix_longer_cmd,
- "show ipv6 bgp X:X::X:X/M longer-prefixes",
- SHOW_STR
- IPV6_STR
- BGP_STR
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
- "Display route and more specific routes\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_UNICAST,
- bgp_show_type_prefix_longer);
- }
- /* old command */
- DEFUN (show_ipv6_mbgp_prefix_longer,
- show_ipv6_mbgp_prefix_longer_cmd,
- "show ipv6 mbgp X:X::X:X/M longer-prefixes",
- SHOW_STR
- IPV6_STR
- MBGP_STR
- "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
- "Display route and more specific routes\n")
- {
- return bgp_show_prefix_longer (vty, argv[0], AFI_IP6, SAFI_MULTICAST,
- bgp_show_type_prefix_longer);
- }
- #endif /* HAVE_IPV6 */
- static struct peer *
- peer_lookup_in_view (struct vty *vty, const char *view_name,
- const char *ip_str)
- {
- int ret;
- struct bgp *bgp;
- struct peer *peer;
- union sockunion su;
- /* BGP structure lookup. */
- if (view_name)
- {
- bgp = bgp_lookup_by_name (view_name);
- if (! bgp)
- {
- vty_out (vty, "Can't find BGP view %s%s", view_name, VTY_NEWLINE);
- return NULL;
- }
- }
- else
- {
- bgp = bgp_get_default ();
- if (! bgp)
- {
- vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
- return NULL;
- }
- }
- /* Get peer sockunion. */
- ret = str2sockunion (ip_str, &su);
- if (ret < 0)
- {
- vty_out (vty, "Malformed address: %s%s", ip_str, VTY_NEWLINE);
- return NULL;
- }
- /* Peer structure lookup. */
- peer = peer_lookup (bgp, &su);
- if (! peer)
- {
- vty_out (vty, "No such neighbor%s", VTY_NEWLINE);
- return NULL;
- }
-
- return peer;
- }
- enum bgp_stats
- {
- BGP_STATS_MAXBITLEN = 0,
- BGP_STATS_RIB,
- BGP_STATS_PREFIXES,
- BGP_STATS_TOTPLEN,
- BGP_STATS_UNAGGREGATEABLE,
- BGP_STATS_MAX_AGGREGATEABLE,
- BGP_STATS_AGGREGATES,
- BGP_STATS_SPACE,
- BGP_STATS_ASPATH_COUNT,
- BGP_STATS_ASPATH_MAXHOPS,
- BGP_STATS_ASPATH_TOTHOPS,
- BGP_STATS_ASPATH_MAXSIZE,
- BGP_STATS_ASPATH_TOTSIZE,
- BGP_STATS_ASN_HIGHEST,
- BGP_STATS_MAX,
- };
- static const char *table_stats_strs[] =
- {
- [BGP_STATS_PREFIXES] = "Total Prefixes",
- [BGP_STATS_TOTPLEN] = "Average prefix length",
- [BGP_STATS_RIB] = "Total Advertisements",
- [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
- [BGP_STATS_MAX_AGGREGATEABLE] = "Maximum aggregateable prefixes",
- [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
- [BGP_STATS_SPACE] = "Address space advertised",
- [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
- [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
- [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
- [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
- [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
- [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
- [BGP_STATS_MAX] = NULL,
- };
- struct bgp_table_stats
- {
- struct bgp_table *table;
- unsigned long long counts[BGP_STATS_MAX];
- };
- #if 0
- #define TALLY_SIGFIG 100000
- static unsigned long
- ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
- {
- unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
- unsigned long res = (newtot * TALLY_SIGFIG) / count;
- unsigned long ret = newtot / count;
-
- if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
- return ret + 1;
- else
- return ret;
- }
- #endif
- static int
- bgp_table_stats_walker (struct thread *t)
- {
- struct bgp_node *rn;
- struct bgp_node *top;
- struct bgp_table_stats *ts = THREAD_ARG (t);
- unsigned int space = 0;
-
- if (!(top = bgp_table_top (ts->table)))
- return 0;
- switch (top->p.family)
- {
- case AF_INET:
- space = IPV4_MAX_BITLEN;
- break;
- case AF_INET6:
- space = IPV6_MAX_BITLEN;
- break;
- }
-
- ts->counts[BGP_STATS_MAXBITLEN] = space;
- for (rn = top; rn; rn = bgp_route_next (rn))
- {
- struct bgp_info *ri;
- struct bgp_node *prn = bgp_node_parent_nolock (rn);
- unsigned int rinum = 0;
-
- if (rn == top)
- continue;
-
- if (!rn->info)
- continue;
-
- ts->counts[BGP_STATS_PREFIXES]++;
- ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
- #if 0
- ts->counts[BGP_STATS_AVGPLEN]
- = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
- ts->counts[BGP_STATS_AVGPLEN],
- rn->p.prefixlen);
- #endif
-
- /* check if the prefix is included by any other announcements */
- while (prn && !prn->info)
- prn = bgp_node_parent_nolock (prn);
-
- if (prn == NULL || prn == top)
- {
- ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
- /* announced address space */
- if (space)
- ts->counts[BGP_STATS_SPACE] += 1 << (space - rn->p.prefixlen);
- }
- else if (prn->info)
- ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
-
- for (ri = rn->info; ri; ri = ri->next)
- {
- rinum++;
- ts->counts[BGP_STATS_RIB]++;
-
- if (ri->attr &&
- (CHECK_FLAG (ri->attr->flag,
- ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))))
- ts->counts[BGP_STATS_AGGREGATES]++;
-
- /* as-path stats */
- if (ri->attr && ri->attr->aspath)
- {
- unsigned int hops = aspath_count_hops (ri->attr->aspath);
- unsigned int size = aspath_size (ri->attr->aspath);
- as_t highest = aspath_highest (ri->attr->aspath);
-
- ts->counts[BGP_STATS_ASPATH_COUNT]++;
-
- if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
- ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
-
- if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
- ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
-
- ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
- ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
- #if 0
- ts->counts[BGP_STATS_ASPATH_AVGHOPS]
- = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
- ts->counts[BGP_STATS_ASPATH_AVGHOPS],
- hops);
- ts->counts[BGP_STATS_ASPATH_AVGSIZE]
- = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
- ts->counts[BGP_STATS_ASPATH_AVGSIZE],
- size);
- #endif
- if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
- ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
- }
- }
- }
- return 0;
- }
- static int
- bgp_table_stats (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi)
- {
- struct bgp_table_stats ts;
- unsigned int i;
-
- if (!bgp->rib[afi][safi])
- {
- vty_out (vty, "%% No RIB exist for the AFI/SAFI%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- memset (&ts, 0, sizeof (ts));
- ts.table = bgp->rib[afi][safi];
- thread_execute (bm->master, bgp_table_stats_walker, &ts, 0);
- vty_out (vty, "BGP %s RIB statistics%s%s",
- afi_safi_print (afi, safi), VTY_NEWLINE, VTY_NEWLINE);
-
- for (i = 0; i < BGP_STATS_MAX; i++)
- {
- if (!table_stats_strs[i])
- continue;
-
- switch (i)
- {
- #if 0
- case BGP_STATS_ASPATH_AVGHOPS:
- case BGP_STATS_ASPATH_AVGSIZE:
- case BGP_STATS_AVGPLEN:
- vty_out (vty, "%-30s: ", table_stats_strs[i]);
- vty_out (vty, "%12.2f",
- (float)ts.counts[i] / (float)TALLY_SIGFIG);
- break;
- #endif
- case BGP_STATS_ASPATH_TOTHOPS:
- case BGP_STATS_ASPATH_TOTSIZE:
- vty_out (vty, "%-30s: ", table_stats_strs[i]);
- vty_out (vty, "%12.2f",
- ts.counts[i] ?
- (float)ts.counts[i] /
- (float)ts.counts[BGP_STATS_ASPATH_COUNT]
- : 0);
- break;
- case BGP_STATS_TOTPLEN:
- vty_out (vty, "%-30s: ", table_stats_strs[i]);
- vty_out (vty, "%12.2f",
- ts.counts[i] ?
- (float)ts.counts[i] /
- (float)ts.counts[BGP_STATS_PREFIXES]
- : 0);
- break;
- case BGP_STATS_SPACE:
- vty_out (vty, "%-30s: ", table_stats_strs[i]);
- vty_out (vty, "%12llu%s", ts.counts[i], VTY_NEWLINE);
- if (ts.counts[BGP_STATS_MAXBITLEN] < 9)
- break;
- vty_out (vty, "%30s: ", "%% announced ");
- vty_out (vty, "%12.2f%s",
- 100 * (float)ts.counts[BGP_STATS_SPACE] /
- (float)((uint64_t)1UL << ts.counts[BGP_STATS_MAXBITLEN]),
- VTY_NEWLINE);
- vty_out (vty, "%30s: ", "/8 equivalent ");
- vty_out (vty, "%12.2f%s",
- (float)ts.counts[BGP_STATS_SPACE] /
- (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 8)),
- VTY_NEWLINE);
- if (ts.counts[BGP_STATS_MAXBITLEN] < 25)
- break;
- vty_out (vty, "%30s: ", "/24 equivalent ");
- vty_out (vty, "%12.2f",
- (float)ts.counts[BGP_STATS_SPACE] /
- (float)(1UL << (ts.counts[BGP_STATS_MAXBITLEN] - 24)));
- break;
- default:
- vty_out (vty, "%-30s: ", table_stats_strs[i]);
- vty_out (vty, "%12llu", ts.counts[i]);
- }
-
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- return CMD_SUCCESS;
- }
- static int
- bgp_table_stats_vty (struct vty *vty, const char *name,
- const char *afi_str, const char *safi_str)
- {
- struct bgp *bgp;
- afi_t afi;
- safi_t safi;
-
- if (name)
- bgp = bgp_lookup_by_name (name);
- else
- bgp = bgp_get_default ();
- if (!bgp)
- {
- vty_out (vty, "%% No such BGP instance exist%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (strncmp (afi_str, "ipv", 3) == 0)
- {
- if (strncmp (afi_str, "ipv4", 4) == 0)
- afi = AFI_IP;
- else if (strncmp (afi_str, "ipv6", 4) == 0)
- afi = AFI_IP6;
- else
- {
- vty_out (vty, "%% Invalid address family %s%s",
- afi_str, VTY_NEWLINE);
- return CMD_WARNING;
- }
- if (strncmp (safi_str, "m", 1) == 0)
- safi = SAFI_MULTICAST;
- else if (strncmp (safi_str, "u", 1) == 0)
- safi = SAFI_UNICAST;
- else if (strncmp (safi_str, "vpnv4", 5) == 0 || strncmp (safi_str, "vpnv6", 5) == 0)
- safi = SAFI_MPLS_LABELED_VPN;
- else
- {
- vty_out (vty, "%% Invalid subsequent address family %s%s",
- safi_str, VTY_NEWLINE);
- return CMD_WARNING;
- }
- }
- else
- {
- vty_out (vty, "%% Invalid address family %s%s",
- afi_str, VTY_NEWLINE);
- return CMD_WARNING;
- }
- return bgp_table_stats (vty, bgp, afi, safi);
- }
- DEFUN (show_bgp_statistics,
- show_bgp_statistics_cmd,
- "show bgp (ipv4|ipv6) (unicast|multicast) statistics",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "BGP RIB advertisement statistics\n")
- {
- return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
- }
- ALIAS (show_bgp_statistics,
- show_bgp_statistics_vpnv4_cmd,
- "show bgp (ipv4) (vpnv4) statistics",
- SHOW_STR
- BGP_STR
- "Address family\n"
- "Address Family modifier\n"
- "BGP RIB advertisement statistics\n")
- DEFUN (show_bgp_statistics_view,
- show_bgp_statistics_view_cmd,
- "show bgp view WORD (ipv4|ipv6) (unicast|multicast) statistics",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "Address family\n"
- "Address family\n"
- "Address Family modifier\n"
- "Address Family modifier\n"
- "BGP RIB advertisement statistics\n")
- {
- return bgp_table_stats_vty (vty, NULL, argv[0], argv[1]);
- }
- ALIAS (show_bgp_statistics_view,
- show_bgp_statistics_view_vpnv4_cmd,
- "show bgp view WORD (ipv4) (vpnv4) statistics",
- SHOW_STR
- BGP_STR
- "BGP view\n"
- "Address family\n"
- "Address Family modifier\n"
- "BGP RIB advertisement statistics\n")
- enum bgp_pcounts
- {
- PCOUNT_ADJ_IN = 0,
- PCOUNT_DAMPED,
- PCOUNT_REMOVED,
- PCOUNT_HISTORY,
- PCOUNT_STALE,
- PCOUNT_VALID,
- PCOUNT_ALL,
- PCOUNT_COUNTED,
- PCOUNT_PFCNT, /* the figure we display to users */
- PCOUNT_MAX,
- };
- static const char *pcount_strs[] =
- {
- [PCOUNT_ADJ_IN] = "Adj-in",
- [PCOUNT_DAMPED] = "Damped",
- [PCOUNT_REMOVED] = "Removed",
- [PCOUNT_HISTORY] = "History",
- [PCOUNT_STALE] = "Stale",
- [PCOUNT_VALID] = "Valid",
- [PCOUNT_ALL] = "All RIB",
- [PCOUNT_COUN
|