123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465 |
- package netlink
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "io/ioutil"
- "net"
- "os"
- "strconv"
- "strings"
- "syscall"
- "unsafe"
- "github.com/vishvananda/netlink/nl"
- "github.com/vishvananda/netns"
- "golang.org/x/sys/unix"
- )
- const (
- SizeofLinkStats32 = 0x5c
- SizeofLinkStats64 = 0xb8
- )
- const (
- TUNTAP_MODE_TUN TuntapMode = unix.IFF_TUN
- TUNTAP_MODE_TAP TuntapMode = unix.IFF_TAP
- TUNTAP_DEFAULTS TuntapFlag = unix.IFF_TUN_EXCL | unix.IFF_ONE_QUEUE
- TUNTAP_VNET_HDR TuntapFlag = unix.IFF_VNET_HDR
- TUNTAP_TUN_EXCL TuntapFlag = unix.IFF_TUN_EXCL
- TUNTAP_NO_PI TuntapFlag = unix.IFF_NO_PI
- TUNTAP_ONE_QUEUE TuntapFlag = unix.IFF_ONE_QUEUE
- TUNTAP_MULTI_QUEUE TuntapFlag = unix.IFF_MULTI_QUEUE
- TUNTAP_MULTI_QUEUE_DEFAULTS TuntapFlag = TUNTAP_MULTI_QUEUE | TUNTAP_NO_PI
- )
- var StringToTuntapModeMap = map[string]TuntapMode{
- "tun": TUNTAP_MODE_TUN,
- "tap": TUNTAP_MODE_TAP,
- }
- func (ttm TuntapMode) String() string {
- switch ttm {
- case TUNTAP_MODE_TUN:
- return "tun"
- case TUNTAP_MODE_TAP:
- return "tap"
- }
- return "unknown"
- }
- const (
- VF_LINK_STATE_AUTO uint32 = 0
- VF_LINK_STATE_ENABLE uint32 = 1
- VF_LINK_STATE_DISABLE uint32 = 2
- )
- var macvlanModes = [...]uint32{
- 0,
- nl.MACVLAN_MODE_PRIVATE,
- nl.MACVLAN_MODE_VEPA,
- nl.MACVLAN_MODE_BRIDGE,
- nl.MACVLAN_MODE_PASSTHRU,
- nl.MACVLAN_MODE_SOURCE,
- }
- func ensureIndex(link *LinkAttrs) {
- if link != nil && link.Index == 0 {
- newlink, _ := LinkByName(link.Name)
- if newlink != nil {
- link.Index = newlink.Attrs().Index
- }
- }
- }
- func (h *Handle) ensureIndex(link *LinkAttrs) {
- if link != nil && link.Index == 0 {
- newlink, _ := h.LinkByName(link.Name)
- if newlink != nil {
- link.Index = newlink.Attrs().Index
- }
- }
- }
- func (h *Handle) LinkSetARPOff(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change |= unix.IFF_NOARP
- msg.Flags |= unix.IFF_NOARP
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func LinkSetARPOff(link Link) error {
- return pkgHandle.LinkSetARPOff(link)
- }
- func (h *Handle) LinkSetARPOn(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change |= unix.IFF_NOARP
- msg.Flags &= ^uint32(unix.IFF_NOARP)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func LinkSetARPOn(link Link) error {
- return pkgHandle.LinkSetARPOn(link)
- }
- func (h *Handle) SetPromiscOn(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_PROMISC
- msg.Flags = unix.IFF_PROMISC
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device.
- // Equivalent to: `ip link set $link allmulticast on`
- func LinkSetAllmulticastOn(link Link) error {
- return pkgHandle.LinkSetAllmulticastOn(link)
- }
- // LinkSetAllmulticastOn enables the reception of all hardware multicast packets for the link device.
- // Equivalent to: `ip link set $link allmulticast on`
- func (h *Handle) LinkSetAllmulticastOn(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_ALLMULTI
- msg.Flags = unix.IFF_ALLMULTI
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device.
- // Equivalent to: `ip link set $link allmulticast off`
- func LinkSetAllmulticastOff(link Link) error {
- return pkgHandle.LinkSetAllmulticastOff(link)
- }
- // LinkSetAllmulticastOff disables the reception of all hardware multicast packets for the link device.
- // Equivalent to: `ip link set $link allmulticast off`
- func (h *Handle) LinkSetAllmulticastOff(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_ALLMULTI
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetMulticastOn enables the reception of multicast packets for the link device.
- // Equivalent to: `ip link set $link multicast on`
- func LinkSetMulticastOn(link Link) error {
- return pkgHandle.LinkSetMulticastOn(link)
- }
- // LinkSetMulticastOn enables the reception of multicast packets for the link device.
- // Equivalent to: `ip link set $link multicast on`
- func (h *Handle) LinkSetMulticastOn(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_MULTICAST
- msg.Flags = unix.IFF_MULTICAST
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
- // Equivalent to: `ip link set $link multicast off`
- func LinkSetMulticastOff(link Link) error {
- return pkgHandle.LinkSetMulticastOff(link)
- }
- // LinkSetAllmulticastOff disables the reception of multicast packets for the link device.
- // Equivalent to: `ip link set $link multicast off`
- func (h *Handle) LinkSetMulticastOff(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_MULTICAST
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
- return pkgHandle.MacvlanMACAddrAdd(link, addr)
- }
- func (h *Handle) MacvlanMACAddrAdd(link Link, addr net.HardwareAddr) error {
- return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_ADD)
- }
- func MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error {
- return pkgHandle.MacvlanMACAddrDel(link, addr)
- }
- func (h *Handle) MacvlanMACAddrDel(link Link, addr net.HardwareAddr) error {
- return h.macvlanMACAddrChange(link, []net.HardwareAddr{addr}, nl.MACVLAN_MACADDR_DEL)
- }
- func MacvlanMACAddrFlush(link Link) error {
- return pkgHandle.MacvlanMACAddrFlush(link)
- }
- func (h *Handle) MacvlanMACAddrFlush(link Link) error {
- return h.macvlanMACAddrChange(link, nil, nl.MACVLAN_MACADDR_FLUSH)
- }
- func MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error {
- return pkgHandle.MacvlanMACAddrSet(link, addrs)
- }
- func (h *Handle) MacvlanMACAddrSet(link Link, addrs []net.HardwareAddr) error {
- return h.macvlanMACAddrChange(link, addrs, nl.MACVLAN_MACADDR_SET)
- }
- func (h *Handle) macvlanMACAddrChange(link Link, addrs []net.HardwareAddr, mode uint32) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
- linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
- inner := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- // IFLA_MACVLAN_MACADDR_MODE = mode
- b := make([]byte, 4)
- native.PutUint32(b, mode)
- inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_MODE, b)
- // populate message with MAC addrs, if necessary
- switch mode {
- case nl.MACVLAN_MACADDR_ADD, nl.MACVLAN_MACADDR_DEL:
- if len(addrs) == 1 {
- inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addrs[0]))
- }
- case nl.MACVLAN_MACADDR_SET:
- mad := inner.AddRtAttr(nl.IFLA_MACVLAN_MACADDR_DATA, nil)
- for _, addr := range addrs {
- mad.AddRtAttr(nl.IFLA_MACVLAN_MACADDR, []byte(addr))
- }
- }
- req.AddData(linkInfo)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetMacvlanMode sets the mode of a macvlan or macvtap link device.
- // Note that passthrough mode cannot be set to and from and will fail.
- // Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode
- func LinkSetMacvlanMode(link Link, mode MacvlanMode) error {
- return pkgHandle.LinkSetMacvlanMode(link, mode)
- }
- // LinkSetMacvlanMode sets the mode of the macvlan or macvtap link device.
- // Note that passthrough mode cannot be set to and from and will fail.
- // Equivalent to: `ip link set $link type (macvlan|macvtap) mode $mode
- func (h *Handle) LinkSetMacvlanMode(link Link, mode MacvlanMode) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
- linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[mode]))
- req.AddData(linkInfo)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func BridgeSetMcastSnoop(link Link, on bool) error {
- return pkgHandle.BridgeSetMcastSnoop(link, on)
- }
- func (h *Handle) BridgeSetMcastSnoop(link Link, on bool) error {
- bridge := link.(*Bridge)
- bridge.MulticastSnooping = &on
- return h.linkModify(bridge, unix.NLM_F_ACK)
- }
- func BridgeSetVlanFiltering(link Link, on bool) error {
- return pkgHandle.BridgeSetVlanFiltering(link, on)
- }
- func (h *Handle) BridgeSetVlanFiltering(link Link, on bool) error {
- bridge := link.(*Bridge)
- bridge.VlanFiltering = &on
- return h.linkModify(bridge, unix.NLM_F_ACK)
- }
- func SetPromiscOn(link Link) error {
- return pkgHandle.SetPromiscOn(link)
- }
- func (h *Handle) SetPromiscOff(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_PROMISC
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func SetPromiscOff(link Link) error {
- return pkgHandle.SetPromiscOff(link)
- }
- // LinkSetUp enables the link device.
- // Equivalent to: `ip link set $link up`
- func LinkSetUp(link Link) error {
- return pkgHandle.LinkSetUp(link)
- }
- // LinkSetUp enables the link device.
- // Equivalent to: `ip link set $link up`
- func (h *Handle) LinkSetUp(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_UP
- msg.Flags = unix.IFF_UP
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetDown disables link device.
- // Equivalent to: `ip link set $link down`
- func LinkSetDown(link Link) error {
- return pkgHandle.LinkSetDown(link)
- }
- // LinkSetDown disables link device.
- // Equivalent to: `ip link set $link down`
- func (h *Handle) LinkSetDown(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Change = unix.IFF_UP
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetMTU sets the mtu of the link device.
- // Equivalent to: `ip link set $link mtu $mtu`
- func LinkSetMTU(link Link, mtu int) error {
- return pkgHandle.LinkSetMTU(link, mtu)
- }
- // LinkSetMTU sets the mtu of the link device.
- // Equivalent to: `ip link set $link mtu $mtu`
- func (h *Handle) LinkSetMTU(link Link, mtu int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(mtu))
- data := nl.NewRtAttr(unix.IFLA_MTU, b)
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetName sets the name of the link device.
- // Equivalent to: `ip link set $link name $name`
- func LinkSetName(link Link, name string) error {
- return pkgHandle.LinkSetName(link, name)
- }
- // LinkSetName sets the name of the link device.
- // Equivalent to: `ip link set $link name $name`
- func (h *Handle) LinkSetName(link Link, name string) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_IFNAME, []byte(name))
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetAlias sets the alias of the link device.
- // Equivalent to: `ip link set dev $link alias $name`
- func LinkSetAlias(link Link, name string) error {
- return pkgHandle.LinkSetAlias(link, name)
- }
- // LinkSetAlias sets the alias of the link device.
- // Equivalent to: `ip link set dev $link alias $name`
- func (h *Handle) LinkSetAlias(link Link, name string) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(name))
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetHardwareAddr sets the hardware address of the link device.
- // Equivalent to: `ip link set $link address $hwaddr`
- func LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
- return pkgHandle.LinkSetHardwareAddr(link, hwaddr)
- }
- // LinkSetHardwareAddr sets the hardware address of the link device.
- // Equivalent to: `ip link set $link address $hwaddr`
- func (h *Handle) LinkSetHardwareAddr(link Link, hwaddr net.HardwareAddr) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(hwaddr))
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfHardwareAddr sets the hardware address of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf mac $hwaddr`
- func LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
- return pkgHandle.LinkSetVfHardwareAddr(link, vf, hwaddr)
- }
- // LinkSetVfHardwareAddr sets the hardware address of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf mac $hwaddr`
- func (h *Handle) LinkSetVfHardwareAddr(link Link, vf int, hwaddr net.HardwareAddr) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfMac{
- Vf: uint32(vf),
- }
- copy(vfmsg.Mac[:], []byte(hwaddr))
- info.AddRtAttr(nl.IFLA_VF_MAC, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfVlan sets the vlan of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf vlan $vlan`
- func LinkSetVfVlan(link Link, vf, vlan int) error {
- return pkgHandle.LinkSetVfVlan(link, vf, vlan)
- }
- // LinkSetVfVlan sets the vlan of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf vlan $vlan`
- func (h *Handle) LinkSetVfVlan(link Link, vf, vlan int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfVlan{
- Vf: uint32(vf),
- Vlan: uint32(vlan),
- }
- info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
- func LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
- return pkgHandle.LinkSetVfVlanQos(link, vf, vlan, qos)
- }
- // LinkSetVfVlanQos sets the vlan and qos priority of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf vlan $vlan qos $qos`
- func (h *Handle) LinkSetVfVlanQos(link Link, vf, vlan, qos int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfVlan{
- Vf: uint32(vf),
- Vlan: uint32(vlan),
- Qos: uint32(qos),
- }
- info.AddRtAttr(nl.IFLA_VF_VLAN, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfTxRate sets the tx rate of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf rate $rate`
- func LinkSetVfTxRate(link Link, vf, rate int) error {
- return pkgHandle.LinkSetVfTxRate(link, vf, rate)
- }
- // LinkSetVfTxRate sets the tx rate of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf rate $rate`
- func (h *Handle) LinkSetVfTxRate(link Link, vf, rate int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfTxRate{
- Vf: uint32(vf),
- Rate: uint32(rate),
- }
- info.AddRtAttr(nl.IFLA_VF_TX_RATE, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfRate sets the min and max tx rate of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
- func LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
- return pkgHandle.LinkSetVfRate(link, vf, minRate, maxRate)
- }
- // LinkSetVfRate sets the min and max tx rate of a vf for the link.
- // Equivalent to: `ip link set $link vf $vf min_tx_rate $min_rate max_tx_rate $max_rate`
- func (h *Handle) LinkSetVfRate(link Link, vf, minRate, maxRate int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfRate{
- Vf: uint32(vf),
- MinTxRate: uint32(minRate),
- MaxTxRate: uint32(maxRate),
- }
- info.AddRtAttr(nl.IFLA_VF_RATE, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfState enables/disables virtual link state on a vf.
- // Equivalent to: `ip link set $link vf $vf state $state`
- func LinkSetVfState(link Link, vf int, state uint32) error {
- return pkgHandle.LinkSetVfState(link, vf, state)
- }
- // LinkSetVfState enables/disables virtual link state on a vf.
- // Equivalent to: `ip link set $link vf $vf state $state`
- func (h *Handle) LinkSetVfState(link Link, vf int, state uint32) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfLinkState{
- Vf: uint32(vf),
- LinkState: state,
- }
- info.AddRtAttr(nl.IFLA_VF_LINK_STATE, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
- // Equivalent to: `ip link set $link vf $vf spoofchk $check`
- func LinkSetVfSpoofchk(link Link, vf int, check bool) error {
- return pkgHandle.LinkSetVfSpoofchk(link, vf, check)
- }
- // LinkSetVfSpoofchk enables/disables spoof check on a vf for the link.
- // Equivalent to: `ip link set $link vf $vf spoofchk $check`
- func (h *Handle) LinkSetVfSpoofchk(link Link, vf int, check bool) error {
- var setting uint32
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- if check {
- setting = 1
- }
- vfmsg := nl.VfSpoofchk{
- Vf: uint32(vf),
- Setting: setting,
- }
- info.AddRtAttr(nl.IFLA_VF_SPOOFCHK, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfTrust enables/disables trust state on a vf for the link.
- // Equivalent to: `ip link set $link vf $vf trust $state`
- func LinkSetVfTrust(link Link, vf int, state bool) error {
- return pkgHandle.LinkSetVfTrust(link, vf, state)
- }
- // LinkSetVfTrust enables/disables trust state on a vf for the link.
- // Equivalent to: `ip link set $link vf $vf trust $state`
- func (h *Handle) LinkSetVfTrust(link Link, vf int, state bool) error {
- var setting uint32
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- if state {
- setting = 1
- }
- vfmsg := nl.VfTrust{
- Vf: uint32(vf),
- Setting: setting,
- }
- info.AddRtAttr(nl.IFLA_VF_TRUST, vfmsg.Serialize())
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetVfNodeGUID sets the node GUID of a vf for the link.
- // Equivalent to: `ip link set dev $link vf $vf node_guid $nodeguid`
- func LinkSetVfNodeGUID(link Link, vf int, nodeguid net.HardwareAddr) error {
- return pkgHandle.LinkSetVfGUID(link, vf, nodeguid, nl.IFLA_VF_IB_NODE_GUID)
- }
- // LinkSetVfPortGUID sets the port GUID of a vf for the link.
- // Equivalent to: `ip link set dev $link vf $vf port_guid $portguid`
- func LinkSetVfPortGUID(link Link, vf int, portguid net.HardwareAddr) error {
- return pkgHandle.LinkSetVfGUID(link, vf, portguid, nl.IFLA_VF_IB_PORT_GUID)
- }
- // LinkSetVfGUID sets the node or port GUID of a vf for the link.
- func (h *Handle) LinkSetVfGUID(link Link, vf int, vfGuid net.HardwareAddr, guidType int) error {
- var err error
- var guid uint64
- buf := bytes.NewBuffer(vfGuid)
- err = binary.Read(buf, binary.BigEndian, &guid)
- if err != nil {
- return err
- }
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- data := nl.NewRtAttr(unix.IFLA_VFINFO_LIST, nil)
- info := data.AddRtAttr(nl.IFLA_VF_INFO, nil)
- vfmsg := nl.VfGUID{
- Vf: uint32(vf),
- GUID: guid,
- }
- info.AddRtAttr(guidType, vfmsg.Serialize())
- req.AddData(data)
- _, err = req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetMaster sets the master of the link device.
- // Equivalent to: `ip link set $link master $master`
- func LinkSetMaster(link Link, master Link) error {
- return pkgHandle.LinkSetMaster(link, master)
- }
- // LinkSetMaster sets the master of the link device.
- // Equivalent to: `ip link set $link master $master`
- func (h *Handle) LinkSetMaster(link Link, master Link) error {
- index := 0
- if master != nil {
- masterBase := master.Attrs()
- h.ensureIndex(masterBase)
- index = masterBase.Index
- }
- if index <= 0 {
- return fmt.Errorf("Device does not exist")
- }
- return h.LinkSetMasterByIndex(link, index)
- }
- // LinkSetNoMaster removes the master of the link device.
- // Equivalent to: `ip link set $link nomaster`
- func LinkSetNoMaster(link Link) error {
- return pkgHandle.LinkSetNoMaster(link)
- }
- // LinkSetNoMaster removes the master of the link device.
- // Equivalent to: `ip link set $link nomaster`
- func (h *Handle) LinkSetNoMaster(link Link) error {
- return h.LinkSetMasterByIndex(link, 0)
- }
- // LinkSetMasterByIndex sets the master of the link device.
- // Equivalent to: `ip link set $link master $master`
- func LinkSetMasterByIndex(link Link, masterIndex int) error {
- return pkgHandle.LinkSetMasterByIndex(link, masterIndex)
- }
- // LinkSetMasterByIndex sets the master of the link device.
- // Equivalent to: `ip link set $link master $master`
- func (h *Handle) LinkSetMasterByIndex(link Link, masterIndex int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(masterIndex))
- data := nl.NewRtAttr(unix.IFLA_MASTER, b)
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetNsPid puts the device into a new network namespace. The
- // pid must be a pid of a running process.
- // Equivalent to: `ip link set $link netns $pid`
- func LinkSetNsPid(link Link, nspid int) error {
- return pkgHandle.LinkSetNsPid(link, nspid)
- }
- // LinkSetNsPid puts the device into a new network namespace. The
- // pid must be a pid of a running process.
- // Equivalent to: `ip link set $link netns $pid`
- func (h *Handle) LinkSetNsPid(link Link, nspid int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(nspid))
- data := nl.NewRtAttr(unix.IFLA_NET_NS_PID, b)
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetNsFd puts the device into a new network namespace. The
- // fd must be an open file descriptor to a network namespace.
- // Similar to: `ip link set $link netns $ns`
- func LinkSetNsFd(link Link, fd int) error {
- return pkgHandle.LinkSetNsFd(link, fd)
- }
- // LinkSetNsFd puts the device into a new network namespace. The
- // fd must be an open file descriptor to a network namespace.
- // Similar to: `ip link set $link netns $ns`
- func (h *Handle) LinkSetNsFd(link Link, fd int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(fd))
- data := nl.NewRtAttr(unix.IFLA_NET_NS_FD, b)
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetXdpFd adds a bpf function to the driver. The fd must be a bpf
- // program loaded with bpf(type=BPF_PROG_TYPE_XDP)
- func LinkSetXdpFd(link Link, fd int) error {
- return LinkSetXdpFdWithFlags(link, fd, 0)
- }
- // LinkSetXdpFdWithFlags adds a bpf function to the driver with the given
- // options. The fd must be a bpf program loaded with bpf(type=BPF_PROG_TYPE_XDP)
- func LinkSetXdpFdWithFlags(link Link, fd, flags int) error {
- base := link.Attrs()
- ensureIndex(base)
- req := nl.NewNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- addXdpAttrs(&LinkXdp{Fd: fd, Flags: uint32(flags)}, req)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func boolAttr(val bool) []byte {
- var v uint8
- if val {
- v = 1
- }
- return nl.Uint8Attr(v)
- }
- type vxlanPortRange struct {
- Lo, Hi uint16
- }
- func addVxlanAttrs(vxlan *Vxlan, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if vxlan.FlowBased {
- vxlan.VxlanId = 0
- }
- data.AddRtAttr(nl.IFLA_VXLAN_ID, nl.Uint32Attr(uint32(vxlan.VxlanId)))
- if vxlan.VtepDevIndex != 0 {
- data.AddRtAttr(nl.IFLA_VXLAN_LINK, nl.Uint32Attr(uint32(vxlan.VtepDevIndex)))
- }
- if vxlan.SrcAddr != nil {
- ip := vxlan.SrcAddr.To4()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_VXLAN_LOCAL, []byte(ip))
- } else {
- ip = vxlan.SrcAddr.To16()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_VXLAN_LOCAL6, []byte(ip))
- }
- }
- }
- if vxlan.Group != nil {
- group := vxlan.Group.To4()
- if group != nil {
- data.AddRtAttr(nl.IFLA_VXLAN_GROUP, []byte(group))
- } else {
- group = vxlan.Group.To16()
- if group != nil {
- data.AddRtAttr(nl.IFLA_VXLAN_GROUP6, []byte(group))
- }
- }
- }
- data.AddRtAttr(nl.IFLA_VXLAN_TTL, nl.Uint8Attr(uint8(vxlan.TTL)))
- data.AddRtAttr(nl.IFLA_VXLAN_TOS, nl.Uint8Attr(uint8(vxlan.TOS)))
- data.AddRtAttr(nl.IFLA_VXLAN_LEARNING, boolAttr(vxlan.Learning))
- data.AddRtAttr(nl.IFLA_VXLAN_PROXY, boolAttr(vxlan.Proxy))
- data.AddRtAttr(nl.IFLA_VXLAN_RSC, boolAttr(vxlan.RSC))
- data.AddRtAttr(nl.IFLA_VXLAN_L2MISS, boolAttr(vxlan.L2miss))
- data.AddRtAttr(nl.IFLA_VXLAN_L3MISS, boolAttr(vxlan.L3miss))
- data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX, boolAttr(vxlan.UDP6ZeroCSumTx))
- data.AddRtAttr(nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX, boolAttr(vxlan.UDP6ZeroCSumRx))
- if vxlan.UDPCSum {
- data.AddRtAttr(nl.IFLA_VXLAN_UDP_CSUM, boolAttr(vxlan.UDPCSum))
- }
- if vxlan.GBP {
- data.AddRtAttr(nl.IFLA_VXLAN_GBP, []byte{})
- }
- if vxlan.FlowBased {
- data.AddRtAttr(nl.IFLA_VXLAN_FLOWBASED, boolAttr(vxlan.FlowBased))
- }
- if vxlan.NoAge {
- data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(0))
- } else if vxlan.Age > 0 {
- data.AddRtAttr(nl.IFLA_VXLAN_AGEING, nl.Uint32Attr(uint32(vxlan.Age)))
- }
- if vxlan.Limit > 0 {
- data.AddRtAttr(nl.IFLA_VXLAN_LIMIT, nl.Uint32Attr(uint32(vxlan.Limit)))
- }
- if vxlan.Port > 0 {
- data.AddRtAttr(nl.IFLA_VXLAN_PORT, htons(uint16(vxlan.Port)))
- }
- if vxlan.PortLow > 0 || vxlan.PortHigh > 0 {
- pr := vxlanPortRange{uint16(vxlan.PortLow), uint16(vxlan.PortHigh)}
- buf := new(bytes.Buffer)
- binary.Write(buf, binary.BigEndian, &pr)
- data.AddRtAttr(nl.IFLA_VXLAN_PORT_RANGE, buf.Bytes())
- }
- }
- func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if bond.Mode >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_MODE, nl.Uint8Attr(uint8(bond.Mode)))
- }
- if bond.ActiveSlave >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_ACTIVE_SLAVE, nl.Uint32Attr(uint32(bond.ActiveSlave)))
- }
- if bond.Miimon >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_MIIMON, nl.Uint32Attr(uint32(bond.Miimon)))
- }
- if bond.UpDelay >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_UPDELAY, nl.Uint32Attr(uint32(bond.UpDelay)))
- }
- if bond.DownDelay >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_DOWNDELAY, nl.Uint32Attr(uint32(bond.DownDelay)))
- }
- if bond.UseCarrier >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_USE_CARRIER, nl.Uint8Attr(uint8(bond.UseCarrier)))
- }
- if bond.ArpInterval >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_ARP_INTERVAL, nl.Uint32Attr(uint32(bond.ArpInterval)))
- }
- if bond.ArpIpTargets != nil {
- msg := data.AddRtAttr(nl.IFLA_BOND_ARP_IP_TARGET, nil)
- for i := range bond.ArpIpTargets {
- ip := bond.ArpIpTargets[i].To4()
- if ip != nil {
- msg.AddRtAttr(i, []byte(ip))
- continue
- }
- ip = bond.ArpIpTargets[i].To16()
- if ip != nil {
- msg.AddRtAttr(i, []byte(ip))
- }
- }
- }
- if bond.ArpValidate >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_ARP_VALIDATE, nl.Uint32Attr(uint32(bond.ArpValidate)))
- }
- if bond.ArpAllTargets >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_ARP_ALL_TARGETS, nl.Uint32Attr(uint32(bond.ArpAllTargets)))
- }
- if bond.Primary >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_PRIMARY, nl.Uint32Attr(uint32(bond.Primary)))
- }
- if bond.PrimaryReselect >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_PRIMARY_RESELECT, nl.Uint8Attr(uint8(bond.PrimaryReselect)))
- }
- if bond.FailOverMac >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_FAIL_OVER_MAC, nl.Uint8Attr(uint8(bond.FailOverMac)))
- }
- if bond.XmitHashPolicy >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_XMIT_HASH_POLICY, nl.Uint8Attr(uint8(bond.XmitHashPolicy)))
- }
- if bond.ResendIgmp >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_RESEND_IGMP, nl.Uint32Attr(uint32(bond.ResendIgmp)))
- }
- if bond.NumPeerNotif >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_NUM_PEER_NOTIF, nl.Uint8Attr(uint8(bond.NumPeerNotif)))
- }
- if bond.AllSlavesActive >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_ALL_SLAVES_ACTIVE, nl.Uint8Attr(uint8(bond.AllSlavesActive)))
- }
- if bond.MinLinks >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_MIN_LINKS, nl.Uint32Attr(uint32(bond.MinLinks)))
- }
- if bond.LpInterval >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_LP_INTERVAL, nl.Uint32Attr(uint32(bond.LpInterval)))
- }
- if bond.PacketsPerSlave >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_PACKETS_PER_SLAVE, nl.Uint32Attr(uint32(bond.PacketsPerSlave)))
- }
- if bond.LacpRate >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_AD_LACP_RATE, nl.Uint8Attr(uint8(bond.LacpRate)))
- }
- if bond.AdSelect >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
- }
- if bond.AdActorSysPrio >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio)))
- }
- if bond.AdUserPortKey >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey)))
- }
- if bond.AdActorSystem != nil {
- data.AddRtAttr(nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem))
- }
- if bond.TlbDynamicLb >= 0 {
- data.AddRtAttr(nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb)))
- }
- }
- func cleanupFds(fds []*os.File) {
- for _, f := range fds {
- f.Close()
- }
- }
- // LinkAdd adds a new link device. The type and features of the device
- // are taken from the parameters in the link object.
- // Equivalent to: `ip link add $link`
- func LinkAdd(link Link) error {
- return pkgHandle.LinkAdd(link)
- }
- // LinkAdd adds a new link device. The type and features of the device
- // are taken from the parameters in the link object.
- // Equivalent to: `ip link add $link`
- func (h *Handle) LinkAdd(link Link) error {
- return h.linkModify(link, unix.NLM_F_CREATE|unix.NLM_F_EXCL|unix.NLM_F_ACK)
- }
- func LinkModify(link Link) error {
- return pkgHandle.LinkModify(link)
- }
- func (h *Handle) LinkModify(link Link) error {
- return h.linkModify(link, unix.NLM_F_REQUEST|unix.NLM_F_ACK)
- }
- func (h *Handle) linkModify(link Link, flags int) error {
- // TODO: support extra data for macvlan
- base := link.Attrs()
- // if tuntap, then the name can be empty, OS will provide a name
- tuntap, isTuntap := link.(*Tuntap)
- if base.Name == "" && !isTuntap {
- return fmt.Errorf("LinkAttrs.Name cannot be empty")
- }
- if isTuntap {
- if tuntap.Mode < unix.IFF_TUN || tuntap.Mode > unix.IFF_TAP {
- return fmt.Errorf("Tuntap.Mode %v unknown", tuntap.Mode)
- }
- queues := tuntap.Queues
- var fds []*os.File
- var req ifReq
- copy(req.Name[:15], base.Name)
- req.Flags = uint16(tuntap.Flags)
- if queues == 0 { //Legacy compatibility
- queues = 1
- if tuntap.Flags == 0 {
- req.Flags = uint16(TUNTAP_DEFAULTS)
- }
- } else {
- // For best peformance set Flags to TUNTAP_MULTI_QUEUE_DEFAULTS | TUNTAP_VNET_HDR
- // when a) KVM has support for this ABI and
- // b) the value of the flag is queryable using the TUNGETIFF ioctl
- if tuntap.Flags == 0 {
- req.Flags = uint16(TUNTAP_MULTI_QUEUE_DEFAULTS)
- }
- }
- req.Flags |= uint16(tuntap.Mode)
- const TUN = "/dev/net/tun"
- for i := 0; i < queues; i++ {
- localReq := req
- fd, err := unix.Open(TUN, os.O_RDWR|syscall.O_CLOEXEC, 0)
- if err != nil {
- cleanupFds(fds)
- return err
- }
- _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TUNSETIFF), uintptr(unsafe.Pointer(&localReq)))
- if errno != 0 {
- // close the new fd
- unix.Close(fd)
- // and the already opened ones
- cleanupFds(fds)
- return fmt.Errorf("Tuntap IOCTL TUNSETIFF failed [%d], errno %v", i, errno)
- }
- _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETOWNER, uintptr(tuntap.Owner))
- if errno != 0 {
- cleanupFds(fds)
- return fmt.Errorf("Tuntap IOCTL TUNSETOWNER failed [%d], errno %v", i, errno)
- }
- _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TUNSETGROUP, uintptr(tuntap.Group))
- if errno != 0 {
- cleanupFds(fds)
- return fmt.Errorf("Tuntap IOCTL TUNSETGROUP failed [%d], errno %v", i, errno)
- }
- // Set the tun device to non-blocking before use. The below comment
- // taken from:
- //
- // https://github.com/mistsys/tuntap/commit/161418c25003bbee77d085a34af64d189df62bea
- //
- // Note there is a complication because in go, if a device node is
- // opened, go sets it to use nonblocking I/O. However a /dev/net/tun
- // doesn't work with epoll until after the TUNSETIFF ioctl has been
- // done. So we open the unix fd directly, do the ioctl, then put the
- // fd in nonblocking mode, an then finally wrap it in a os.File,
- // which will see the nonblocking mode and add the fd to the
- // pollable set, so later on when we Read() from it blocked the
- // calling thread in the kernel.
- //
- // See
- // https://github.com/golang/go/issues/30426
- // which got exposed in go 1.13 by the fix to
- // https://github.com/golang/go/issues/30624
- err = unix.SetNonblock(fd, true)
- if err != nil {
- cleanupFds(fds)
- return fmt.Errorf("Tuntap set to non-blocking failed [%d], err %v", i, err)
- }
- // create the file from the file descriptor and store it
- file := os.NewFile(uintptr(fd), TUN)
- fds = append(fds, file)
- // 1) we only care for the name of the first tap in the multi queue set
- // 2) if the original name was empty, the localReq has now the actual name
- //
- // In addition:
- // This ensures that the link name is always identical to what the kernel returns.
- // Not only in case of an empty name, but also when using name templates.
- // e.g. when the provided name is "tap%d", the kernel replaces %d with the next available number.
- if i == 0 {
- link.Attrs().Name = strings.Trim(string(localReq.Name[:]), "\x00")
- }
- }
- control := func(file *os.File, f func(fd uintptr)) error {
- name := file.Name()
- conn, err := file.SyscallConn()
- if err != nil {
- return fmt.Errorf("SyscallConn() failed on %s: %v", name, err)
- }
- if err := conn.Control(f); err != nil {
- return fmt.Errorf("Failed to get file descriptor for %s: %v", name, err)
- }
- return nil
- }
- // only persist interface if NonPersist is NOT set
- if !tuntap.NonPersist {
- var errno syscall.Errno
- if err := control(fds[0], func(fd uintptr) {
- _, _, errno = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 1)
- }); err != nil {
- return err
- }
- if errno != 0 {
- cleanupFds(fds)
- return fmt.Errorf("Tuntap IOCTL TUNSETPERSIST failed, errno %v", errno)
- }
- }
- h.ensureIndex(base)
- // can't set master during create, so set it afterwards
- if base.MasterIndex != 0 {
- // TODO: verify MasterIndex is actually a bridge?
- err := h.LinkSetMasterByIndex(link, base.MasterIndex)
- if err != nil {
- // un-persist (e.g. allow the interface to be removed) the tuntap
- // should not hurt if not set prior, condition might be not needed
- if !tuntap.NonPersist {
- // ignore error
- _ = control(fds[0], func(fd uintptr) {
- _, _, _ = unix.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.TUNSETPERSIST), 0)
- })
- }
- cleanupFds(fds)
- return err
- }
- }
- if tuntap.Queues == 0 {
- cleanupFds(fds)
- } else {
- tuntap.Fds = fds
- }
- return nil
- }
- req := h.newNetlinkRequest(unix.RTM_NEWLINK, flags)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- // TODO: make it shorter
- if base.Flags&net.FlagUp != 0 {
- msg.Change = unix.IFF_UP
- msg.Flags = unix.IFF_UP
- }
- if base.Flags&net.FlagBroadcast != 0 {
- msg.Change |= unix.IFF_BROADCAST
- msg.Flags |= unix.IFF_BROADCAST
- }
- if base.Flags&net.FlagLoopback != 0 {
- msg.Change |= unix.IFF_LOOPBACK
- msg.Flags |= unix.IFF_LOOPBACK
- }
- if base.Flags&net.FlagPointToPoint != 0 {
- msg.Change |= unix.IFF_POINTOPOINT
- msg.Flags |= unix.IFF_POINTOPOINT
- }
- if base.Flags&net.FlagMulticast != 0 {
- msg.Change |= unix.IFF_MULTICAST
- msg.Flags |= unix.IFF_MULTICAST
- }
- if base.Index != 0 {
- msg.Index = int32(base.Index)
- }
- req.AddData(msg)
- if base.ParentIndex != 0 {
- b := make([]byte, 4)
- native.PutUint32(b, uint32(base.ParentIndex))
- data := nl.NewRtAttr(unix.IFLA_LINK, b)
- req.AddData(data)
- } else if link.Type() == "ipvlan" || link.Type() == "ipoib" {
- return fmt.Errorf("Can't create %s link without ParentIndex", link.Type())
- }
- nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(base.Name))
- req.AddData(nameData)
- if base.Alias != "" {
- alias := nl.NewRtAttr(unix.IFLA_IFALIAS, []byte(base.Alias))
- req.AddData(alias)
- }
- if base.MTU > 0 {
- mtu := nl.NewRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
- req.AddData(mtu)
- }
- if base.TxQLen >= 0 {
- qlen := nl.NewRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
- req.AddData(qlen)
- }
- if base.HardwareAddr != nil {
- hwaddr := nl.NewRtAttr(unix.IFLA_ADDRESS, []byte(base.HardwareAddr))
- req.AddData(hwaddr)
- }
- if base.NumTxQueues > 0 {
- txqueues := nl.NewRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues)))
- req.AddData(txqueues)
- }
- if base.NumRxQueues > 0 {
- rxqueues := nl.NewRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues)))
- req.AddData(rxqueues)
- }
- if base.GSOMaxSegs > 0 {
- gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SEGS, nl.Uint32Attr(base.GSOMaxSegs))
- req.AddData(gsoAttr)
- }
- if base.GSOMaxSize > 0 {
- gsoAttr := nl.NewRtAttr(unix.IFLA_GSO_MAX_SIZE, nl.Uint32Attr(base.GSOMaxSize))
- req.AddData(gsoAttr)
- }
- if base.Group > 0 {
- groupAttr := nl.NewRtAttr(unix.IFLA_GROUP, nl.Uint32Attr(base.Group))
- req.AddData(groupAttr)
- }
- if base.Namespace != nil {
- var attr *nl.RtAttr
- switch ns := base.Namespace.(type) {
- case NsPid:
- val := nl.Uint32Attr(uint32(ns))
- attr = nl.NewRtAttr(unix.IFLA_NET_NS_PID, val)
- case NsFd:
- val := nl.Uint32Attr(uint32(ns))
- attr = nl.NewRtAttr(unix.IFLA_NET_NS_FD, val)
- }
- req.AddData(attr)
- }
- if base.Xdp != nil {
- addXdpAttrs(base.Xdp, req)
- }
- linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
- linkInfo.AddRtAttr(nl.IFLA_INFO_KIND, nl.NonZeroTerminated(link.Type()))
- switch link := link.(type) {
- case *Vlan:
- b := make([]byte, 2)
- native.PutUint16(b, uint16(link.VlanId))
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_VLAN_ID, b)
- if link.VlanProtocol != VLAN_PROTOCOL_UNKNOWN {
- data.AddRtAttr(nl.IFLA_VLAN_PROTOCOL, htons(uint16(link.VlanProtocol)))
- }
- case *Veth:
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- peer := data.AddRtAttr(nl.VETH_INFO_PEER, nil)
- nl.NewIfInfomsgChild(peer, unix.AF_UNSPEC)
- peer.AddRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(link.PeerName))
- if base.TxQLen >= 0 {
- peer.AddRtAttr(unix.IFLA_TXQLEN, nl.Uint32Attr(uint32(base.TxQLen)))
- }
- if base.NumTxQueues > 0 {
- peer.AddRtAttr(unix.IFLA_NUM_TX_QUEUES, nl.Uint32Attr(uint32(base.NumTxQueues)))
- }
- if base.NumRxQueues > 0 {
- peer.AddRtAttr(unix.IFLA_NUM_RX_QUEUES, nl.Uint32Attr(uint32(base.NumRxQueues)))
- }
- if base.MTU > 0 {
- peer.AddRtAttr(unix.IFLA_MTU, nl.Uint32Attr(uint32(base.MTU)))
- }
- if link.PeerHardwareAddr != nil {
- peer.AddRtAttr(unix.IFLA_ADDRESS, []byte(link.PeerHardwareAddr))
- }
- if link.PeerNamespace != nil {
- switch ns := link.PeerNamespace.(type) {
- case NsPid:
- val := nl.Uint32Attr(uint32(ns))
- peer.AddRtAttr(unix.IFLA_NET_NS_PID, val)
- case NsFd:
- val := nl.Uint32Attr(uint32(ns))
- peer.AddRtAttr(unix.IFLA_NET_NS_FD, val)
- }
- }
- case *Vxlan:
- addVxlanAttrs(link, linkInfo)
- case *Bond:
- addBondAttrs(link, linkInfo)
- case *IPVlan:
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
- data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
- case *IPVtap:
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_IPVLAN_MODE, nl.Uint16Attr(uint16(link.Mode)))
- data.AddRtAttr(nl.IFLA_IPVLAN_FLAG, nl.Uint16Attr(uint16(link.Flag)))
- case *Macvlan:
- if link.Mode != MACVLAN_MODE_DEFAULT {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
- }
- case *Macvtap:
- if link.Mode != MACVLAN_MODE_DEFAULT {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_MACVLAN_MODE, nl.Uint32Attr(macvlanModes[link.Mode]))
- }
- case *Geneve:
- addGeneveAttrs(link, linkInfo)
- case *Gretap:
- addGretapAttrs(link, linkInfo)
- case *Iptun:
- addIptunAttrs(link, linkInfo)
- case *Ip6tnl:
- addIp6tnlAttrs(link, linkInfo)
- case *Sittun:
- addSittunAttrs(link, linkInfo)
- case *Gretun:
- addGretunAttrs(link, linkInfo)
- case *Vti:
- addVtiAttrs(link, linkInfo)
- case *Vrf:
- addVrfAttrs(link, linkInfo)
- case *Bridge:
- addBridgeAttrs(link, linkInfo)
- case *GTP:
- addGTPAttrs(link, linkInfo)
- case *Xfrmi:
- addXfrmiAttrs(link, linkInfo)
- case *IPoIB:
- addIPoIBAttrs(link, linkInfo)
- case *BareUDP:
- addBareUDPAttrs(link, linkInfo)
- }
- req.AddData(linkInfo)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- if err != nil {
- return err
- }
- h.ensureIndex(base)
- // can't set master during create, so set it afterwards
- if base.MasterIndex != 0 {
- // TODO: verify MasterIndex is actually a bridge?
- return h.LinkSetMasterByIndex(link, base.MasterIndex)
- }
- return nil
- }
- // LinkDel deletes link device. Either Index or Name must be set in
- // the link object for it to be deleted. The other values are ignored.
- // Equivalent to: `ip link del $link`
- func LinkDel(link Link) error {
- return pkgHandle.LinkDel(link)
- }
- // LinkDel deletes link device. Either Index or Name must be set in
- // the link object for it to be deleted. The other values are ignored.
- // Equivalent to: `ip link del $link`
- func (h *Handle) LinkDel(link Link) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_DELLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func (h *Handle) linkByNameDump(name string) (Link, error) {
- links, err := h.LinkList()
- if err != nil {
- return nil, err
- }
- for _, link := range links {
- if link.Attrs().Name == name {
- return link, nil
- }
- }
- return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)}
- }
- func (h *Handle) linkByAliasDump(alias string) (Link, error) {
- links, err := h.LinkList()
- if err != nil {
- return nil, err
- }
- for _, link := range links {
- if link.Attrs().Alias == alias {
- return link, nil
- }
- }
- return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)}
- }
- // LinkByName finds a link by name and returns a pointer to the object.
- func LinkByName(name string) (Link, error) {
- return pkgHandle.LinkByName(name)
- }
- // LinkByName finds a link by name and returns a pointer to the object.
- func (h *Handle) LinkByName(name string) (Link, error) {
- if h.lookupByDump {
- return h.linkByNameDump(name)
- }
- req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- req.AddData(msg)
- attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
- req.AddData(attr)
- nameData := nl.NewRtAttr(unix.IFLA_IFNAME, nl.ZeroTerminated(name))
- req.AddData(nameData)
- link, err := execGetLink(req)
- if err == unix.EINVAL {
- // older kernels don't support looking up via IFLA_IFNAME
- // so fall back to dumping all links
- h.lookupByDump = true
- return h.linkByNameDump(name)
- }
- return link, err
- }
- // LinkByAlias finds a link by its alias and returns a pointer to the object.
- // If there are multiple links with the alias it returns the first one
- func LinkByAlias(alias string) (Link, error) {
- return pkgHandle.LinkByAlias(alias)
- }
- // LinkByAlias finds a link by its alias and returns a pointer to the object.
- // If there are multiple links with the alias it returns the first one
- func (h *Handle) LinkByAlias(alias string) (Link, error) {
- if h.lookupByDump {
- return h.linkByAliasDump(alias)
- }
- req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- req.AddData(msg)
- attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
- req.AddData(attr)
- nameData := nl.NewRtAttr(unix.IFLA_IFALIAS, nl.ZeroTerminated(alias))
- req.AddData(nameData)
- link, err := execGetLink(req)
- if err == unix.EINVAL {
- // older kernels don't support looking up via IFLA_IFALIAS
- // so fall back to dumping all links
- h.lookupByDump = true
- return h.linkByAliasDump(alias)
- }
- return link, err
- }
- // LinkByIndex finds a link by index and returns a pointer to the object.
- func LinkByIndex(index int) (Link, error) {
- return pkgHandle.LinkByIndex(index)
- }
- // LinkByIndex finds a link by index and returns a pointer to the object.
- func (h *Handle) LinkByIndex(index int) (Link, error) {
- req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(index)
- req.AddData(msg)
- attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
- req.AddData(attr)
- return execGetLink(req)
- }
- func execGetLink(req *nl.NetlinkRequest) (Link, error) {
- msgs, err := req.Execute(unix.NETLINK_ROUTE, 0)
- if err != nil {
- if errno, ok := err.(syscall.Errno); ok {
- if errno == unix.ENODEV {
- return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
- }
- }
- return nil, err
- }
- switch {
- case len(msgs) == 0:
- return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
- case len(msgs) == 1:
- return LinkDeserialize(nil, msgs[0])
- default:
- return nil, fmt.Errorf("More than one link found")
- }
- }
- // LinkDeserialize deserializes a raw message received from netlink into
- // a link object.
- func LinkDeserialize(hdr *unix.NlMsghdr, m []byte) (Link, error) {
- msg := nl.DeserializeIfInfomsg(m)
- attrs, err := nl.ParseRouteAttr(m[msg.Len():])
- if err != nil {
- return nil, err
- }
- base := NewLinkAttrs()
- base.Index = int(msg.Index)
- base.RawFlags = msg.Flags
- base.Flags = linkFlags(msg.Flags)
- base.EncapType = msg.EncapType()
- base.NetNsID = -1
- if msg.Flags&unix.IFF_PROMISC != 0 {
- base.Promisc = 1
- }
- if msg.Flags&unix.IFF_ALLMULTI != 0 {
- base.Allmulti = 1
- }
- if msg.Flags&unix.IFF_MULTICAST != 0 {
- base.Multi = 1
- }
- var (
- link Link
- stats32 *LinkStatistics32
- stats64 *LinkStatistics64
- linkType string
- linkSlave LinkSlave
- slaveType string
- )
- for _, attr := range attrs {
- switch attr.Attr.Type {
- case unix.IFLA_LINKINFO:
- infos, err := nl.ParseRouteAttr(attr.Value)
- if err != nil {
- return nil, err
- }
- for _, info := range infos {
- switch info.Attr.Type {
- case nl.IFLA_INFO_KIND:
- linkType = string(info.Value[:len(info.Value)-1])
- switch linkType {
- case "dummy":
- link = &Dummy{}
- case "ifb":
- link = &Ifb{}
- case "bridge":
- link = &Bridge{}
- case "vlan":
- link = &Vlan{}
- case "veth":
- link = &Veth{}
- case "wireguard":
- link = &Wireguard{}
- case "vxlan":
- link = &Vxlan{}
- case "bond":
- link = &Bond{}
- case "ipvlan":
- link = &IPVlan{}
- case "ipvtap":
- link = &IPVtap{}
- case "macvlan":
- link = &Macvlan{}
- case "macvtap":
- link = &Macvtap{}
- case "geneve":
- link = &Geneve{}
- case "gretap":
- link = &Gretap{}
- case "ip6gretap":
- link = &Gretap{}
- case "ipip":
- link = &Iptun{}
- case "ip6tnl":
- link = &Ip6tnl{}
- case "sit":
- link = &Sittun{}
- case "gre":
- link = &Gretun{}
- case "ip6gre":
- link = &Gretun{}
- case "vti", "vti6":
- link = &Vti{}
- case "vrf":
- link = &Vrf{}
- case "gtp":
- link = >P{}
- case "xfrm":
- link = &Xfrmi{}
- case "tun":
- link = &Tuntap{}
- case "ipoib":
- link = &IPoIB{}
- case "can":
- link = &Can{}
- case "bareudp":
- link = &BareUDP{}
- default:
- link = &GenericLink{LinkType: linkType}
- }
- case nl.IFLA_INFO_DATA:
- data, err := nl.ParseRouteAttr(info.Value)
- if err != nil {
- return nil, err
- }
- switch linkType {
- case "vlan":
- parseVlanData(link, data)
- case "vxlan":
- parseVxlanData(link, data)
- case "bond":
- parseBondData(link, data)
- case "ipvlan":
- parseIPVlanData(link, data)
- case "ipvtap":
- parseIPVtapData(link, data)
- case "macvlan":
- parseMacvlanData(link, data)
- case "macvtap":
- parseMacvtapData(link, data)
- case "geneve":
- parseGeneveData(link, data)
- case "gretap":
- parseGretapData(link, data)
- case "ip6gretap":
- parseGretapData(link, data)
- case "ipip":
- parseIptunData(link, data)
- case "ip6tnl":
- parseIp6tnlData(link, data)
- case "sit":
- parseSittunData(link, data)
- case "gre":
- parseGretunData(link, data)
- case "ip6gre":
- parseGretunData(link, data)
- case "vti", "vti6":
- parseVtiData(link, data)
- case "vrf":
- parseVrfData(link, data)
- case "bridge":
- parseBridgeData(link, data)
- case "gtp":
- parseGTPData(link, data)
- case "xfrm":
- parseXfrmiData(link, data)
- case "tun":
- parseTuntapData(link, data)
- case "ipoib":
- parseIPoIBData(link, data)
- case "can":
- parseCanData(link, data)
- case "bareudp":
- parseBareUDPData(link, data)
- }
- case nl.IFLA_INFO_SLAVE_KIND:
- slaveType = string(info.Value[:len(info.Value)-1])
- switch slaveType {
- case "bond":
- linkSlave = &BondSlave{}
- case "vrf":
- linkSlave = &VrfSlave{}
- }
- case nl.IFLA_INFO_SLAVE_DATA:
- switch slaveType {
- case "bond":
- data, err := nl.ParseRouteAttr(info.Value)
- if err != nil {
- return nil, err
- }
- parseBondSlaveData(linkSlave, data)
- case "vrf":
- data, err := nl.ParseRouteAttr(info.Value)
- if err != nil {
- return nil, err
- }
- parseVrfSlaveData(linkSlave, data)
- }
- }
- }
- case unix.IFLA_ADDRESS:
- var nonzero bool
- for _, b := range attr.Value {
- if b != 0 {
- nonzero = true
- }
- }
- if nonzero {
- base.HardwareAddr = attr.Value[:]
- }
- case unix.IFLA_IFNAME:
- base.Name = string(attr.Value[:len(attr.Value)-1])
- case unix.IFLA_MTU:
- base.MTU = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_LINK:
- base.ParentIndex = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_MASTER:
- base.MasterIndex = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_TXQLEN:
- base.TxQLen = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_IFALIAS:
- base.Alias = string(attr.Value[:len(attr.Value)-1])
- case unix.IFLA_STATS:
- stats32 = new(LinkStatistics32)
- if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats32); err != nil {
- return nil, err
- }
- case unix.IFLA_STATS64:
- stats64 = new(LinkStatistics64)
- if err := binary.Read(bytes.NewBuffer(attr.Value[:]), nl.NativeEndian(), stats64); err != nil {
- return nil, err
- }
- case unix.IFLA_XDP:
- xdp, err := parseLinkXdp(attr.Value[:])
- if err != nil {
- return nil, err
- }
- base.Xdp = xdp
- case unix.IFLA_PROTINFO | unix.NLA_F_NESTED:
- if hdr != nil && hdr.Type == unix.RTM_NEWLINK &&
- msg.Family == unix.AF_BRIDGE {
- attrs, err := nl.ParseRouteAttr(attr.Value[:])
- if err != nil {
- return nil, err
- }
- protinfo := parseProtinfo(attrs)
- base.Protinfo = &protinfo
- }
- case unix.IFLA_OPERSTATE:
- base.OperState = LinkOperState(uint8(attr.Value[0]))
- case unix.IFLA_PHYS_SWITCH_ID:
- base.PhysSwitchID = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_LINK_NETNSID:
- base.NetNsID = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_GSO_MAX_SIZE:
- base.GSOMaxSize = native.Uint32(attr.Value[0:4])
- case unix.IFLA_GSO_MAX_SEGS:
- base.GSOMaxSegs = native.Uint32(attr.Value[0:4])
- case unix.IFLA_VFINFO_LIST:
- data, err := nl.ParseRouteAttr(attr.Value)
- if err != nil {
- return nil, err
- }
- vfs, err := parseVfInfoList(data)
- if err != nil {
- return nil, err
- }
- base.Vfs = vfs
- case unix.IFLA_NUM_TX_QUEUES:
- base.NumTxQueues = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_NUM_RX_QUEUES:
- base.NumRxQueues = int(native.Uint32(attr.Value[0:4]))
- case unix.IFLA_GROUP:
- base.Group = native.Uint32(attr.Value[0:4])
- }
- }
- if stats64 != nil {
- base.Statistics = (*LinkStatistics)(stats64)
- } else if stats32 != nil {
- base.Statistics = (*LinkStatistics)(stats32.to64())
- }
- // Links that don't have IFLA_INFO_KIND are hardware devices
- if link == nil {
- link = &Device{}
- }
- *link.Attrs() = base
- link.Attrs().Slave = linkSlave
- // If the tuntap attributes are not updated by netlink due to
- // an older driver, use sysfs
- if link != nil && linkType == "tun" {
- tuntap := link.(*Tuntap)
- if tuntap.Mode == 0 {
- ifname := tuntap.Attrs().Name
- if flags, err := readSysPropAsInt64(ifname, "tun_flags"); err == nil {
- if flags&unix.IFF_TUN != 0 {
- tuntap.Mode = unix.IFF_TUN
- } else if flags&unix.IFF_TAP != 0 {
- tuntap.Mode = unix.IFF_TAP
- }
- tuntap.NonPersist = false
- if flags&unix.IFF_PERSIST == 0 {
- tuntap.NonPersist = true
- }
- }
- // The sysfs interface for owner/group returns -1 for root user, instead of returning 0.
- // So explicitly check for negative value, before assigning the owner uid/gid.
- if owner, err := readSysPropAsInt64(ifname, "owner"); err == nil && owner > 0 {
- tuntap.Owner = uint32(owner)
- }
- if group, err := readSysPropAsInt64(ifname, "group"); err == nil && group > 0 {
- tuntap.Group = uint32(group)
- }
- }
- }
- return link, nil
- }
- func readSysPropAsInt64(ifname, prop string) (int64, error) {
- fname := fmt.Sprintf("/sys/class/net/%s/%s", ifname, prop)
- contents, err := ioutil.ReadFile(fname)
- if err != nil {
- return 0, err
- }
- num, err := strconv.ParseInt(strings.TrimSpace(string(contents)), 0, 64)
- if err == nil {
- return num, nil
- }
- return 0, err
- }
- // LinkList gets a list of link devices.
- // Equivalent to: `ip link show`
- func LinkList() ([]Link, error) {
- return pkgHandle.LinkList()
- }
- // LinkList gets a list of link devices.
- // Equivalent to: `ip link show`
- func (h *Handle) LinkList() ([]Link, error) {
- // NOTE(vish): This duplicates functionality in net/iface_linux.go, but we need
- // to get the message ourselves to parse link type.
- req := h.newNetlinkRequest(unix.RTM_GETLINK, unix.NLM_F_DUMP)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- req.AddData(msg)
- attr := nl.NewRtAttr(unix.IFLA_EXT_MASK, nl.Uint32Attr(nl.RTEXT_FILTER_VF))
- req.AddData(attr)
- msgs, err := req.Execute(unix.NETLINK_ROUTE, unix.RTM_NEWLINK)
- if err != nil {
- return nil, err
- }
- var res []Link
- for _, m := range msgs {
- link, err := LinkDeserialize(nil, m)
- if err != nil {
- return nil, err
- }
- res = append(res, link)
- }
- return res, nil
- }
- // LinkUpdate is used to pass information back from LinkSubscribe()
- type LinkUpdate struct {
- nl.IfInfomsg
- Header unix.NlMsghdr
- Link
- }
- // LinkSubscribe takes a chan down which notifications will be sent
- // when links change. Close the 'done' chan to stop subscription.
- func LinkSubscribe(ch chan<- LinkUpdate, done <-chan struct{}) error {
- return linkSubscribeAt(netns.None(), netns.None(), ch, done, nil, false)
- }
- // LinkSubscribeAt works like LinkSubscribe plus it allows the caller
- // to choose the network namespace in which to subscribe (ns).
- func LinkSubscribeAt(ns netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}) error {
- return linkSubscribeAt(ns, netns.None(), ch, done, nil, false)
- }
- // LinkSubscribeOptions contains a set of options to use with
- // LinkSubscribeWithOptions.
- type LinkSubscribeOptions struct {
- Namespace *netns.NsHandle
- ErrorCallback func(error)
- ListExisting bool
- }
- // LinkSubscribeWithOptions work like LinkSubscribe but enable to
- // provide additional options to modify the behavior. Currently, the
- // namespace can be provided as well as an error callback.
- func LinkSubscribeWithOptions(ch chan<- LinkUpdate, done <-chan struct{}, options LinkSubscribeOptions) error {
- if options.Namespace == nil {
- none := netns.None()
- options.Namespace = &none
- }
- return linkSubscribeAt(*options.Namespace, netns.None(), ch, done, options.ErrorCallback, options.ListExisting)
- }
- func linkSubscribeAt(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-chan struct{}, cberr func(error), listExisting bool) error {
- s, err := nl.SubscribeAt(newNs, curNs, unix.NETLINK_ROUTE, unix.RTNLGRP_LINK)
- if err != nil {
- return err
- }
- if done != nil {
- go func() {
- <-done
- s.Close()
- }()
- }
- if listExisting {
- req := pkgHandle.newNetlinkRequest(unix.RTM_GETLINK,
- unix.NLM_F_DUMP)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- req.AddData(msg)
- if err := s.Send(req); err != nil {
- return err
- }
- }
- go func() {
- defer close(ch)
- for {
- msgs, from, err := s.Receive()
- if err != nil {
- if cberr != nil {
- cberr(fmt.Errorf("Receive failed: %v",
- err))
- }
- return
- }
- if from.Pid != nl.PidKernel {
- if cberr != nil {
- cberr(fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel))
- }
- continue
- }
- for _, m := range msgs {
- if m.Header.Type == unix.NLMSG_DONE {
- continue
- }
- if m.Header.Type == unix.NLMSG_ERROR {
- error := int32(native.Uint32(m.Data[0:4]))
- if error == 0 {
- continue
- }
- if cberr != nil {
- cberr(fmt.Errorf("error message: %v",
- syscall.Errno(-error)))
- }
- continue
- }
- ifmsg := nl.DeserializeIfInfomsg(m.Data)
- header := unix.NlMsghdr(m.Header)
- link, err := LinkDeserialize(&header, m.Data)
- if err != nil {
- if cberr != nil {
- cberr(err)
- }
- continue
- }
- ch <- LinkUpdate{IfInfomsg: *ifmsg, Header: header, Link: link}
- }
- }
- }()
- return nil
- }
- func LinkSetHairpin(link Link, mode bool) error {
- return pkgHandle.LinkSetHairpin(link, mode)
- }
- func (h *Handle) LinkSetHairpin(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_MODE)
- }
- func LinkSetGuard(link Link, mode bool) error {
- return pkgHandle.LinkSetGuard(link, mode)
- }
- func (h *Handle) LinkSetGuard(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_GUARD)
- }
- func LinkSetFastLeave(link Link, mode bool) error {
- return pkgHandle.LinkSetFastLeave(link, mode)
- }
- func (h *Handle) LinkSetFastLeave(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_FAST_LEAVE)
- }
- func LinkSetLearning(link Link, mode bool) error {
- return pkgHandle.LinkSetLearning(link, mode)
- }
- func (h *Handle) LinkSetLearning(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_LEARNING)
- }
- func LinkSetRootBlock(link Link, mode bool) error {
- return pkgHandle.LinkSetRootBlock(link, mode)
- }
- func (h *Handle) LinkSetRootBlock(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROTECT)
- }
- func LinkSetFlood(link Link, mode bool) error {
- return pkgHandle.LinkSetFlood(link, mode)
- }
- func (h *Handle) LinkSetFlood(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
- }
- func LinkSetBrProxyArp(link Link, mode bool) error {
- return pkgHandle.LinkSetBrProxyArp(link, mode)
- }
- func (h *Handle) LinkSetBrProxyArp(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP)
- }
- func LinkSetBrProxyArpWiFi(link Link, mode bool) error {
- return pkgHandle.LinkSetBrProxyArpWiFi(link, mode)
- }
- func (h *Handle) LinkSetBrProxyArpWiFi(link Link, mode bool) error {
- return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_PROXYARP_WIFI)
- }
- func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_BRIDGE)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- br := nl.NewRtAttr(unix.IFLA_PROTINFO|unix.NLA_F_NESTED, nil)
- br.AddRtAttr(attr, boolToByte(mode))
- req.AddData(br)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- if err != nil {
- return err
- }
- return nil
- }
- // LinkSetTxQLen sets the transaction queue length for the link.
- // Equivalent to: `ip link set $link txqlen $qlen`
- func LinkSetTxQLen(link Link, qlen int) error {
- return pkgHandle.LinkSetTxQLen(link, qlen)
- }
- // LinkSetTxQLen sets the transaction queue length for the link.
- // Equivalent to: `ip link set $link txqlen $qlen`
- func (h *Handle) LinkSetTxQLen(link Link, qlen int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(qlen))
- data := nl.NewRtAttr(unix.IFLA_TXQLEN, b)
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetGroup sets the link group id which can be used to perform mass actions
- // with iproute2 as well use it as a reference in nft filters.
- // Equivalent to: `ip link set $link group $id`
- func LinkSetGroup(link Link, group int) error {
- return pkgHandle.LinkSetGroup(link, group)
- }
- // LinkSetGroup sets the link group id which can be used to perform mass actions
- // with iproute2 as well use it as a reference in nft filters.
- // Equivalent to: `ip link set $link group $id`
- func (h *Handle) LinkSetGroup(link Link, group int) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(group))
- data := nl.NewRtAttr(unix.IFLA_GROUP, b)
- req.AddData(data)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- func parseVlanData(link Link, data []syscall.NetlinkRouteAttr) {
- vlan := link.(*Vlan)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_VLAN_ID:
- vlan.VlanId = int(native.Uint16(datum.Value[0:2]))
- case nl.IFLA_VLAN_PROTOCOL:
- vlan.VlanProtocol = VlanProtocol(int(ntohs(datum.Value[0:2])))
- }
- }
- }
- func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
- vxlan := link.(*Vxlan)
- for _, datum := range data {
- // NOTE(vish): Apparently some messages can be sent with no value.
- // We special case GBP here to not change existing
- // functionality. It appears that GBP sends a datum.Value
- // of null.
- if len(datum.Value) == 0 && datum.Attr.Type != nl.IFLA_VXLAN_GBP {
- continue
- }
- switch datum.Attr.Type {
- case nl.IFLA_VXLAN_ID:
- vxlan.VxlanId = int(native.Uint32(datum.Value[0:4]))
- case nl.IFLA_VXLAN_LINK:
- vxlan.VtepDevIndex = int(native.Uint32(datum.Value[0:4]))
- case nl.IFLA_VXLAN_LOCAL:
- vxlan.SrcAddr = net.IP(datum.Value[0:4])
- case nl.IFLA_VXLAN_LOCAL6:
- vxlan.SrcAddr = net.IP(datum.Value[0:16])
- case nl.IFLA_VXLAN_GROUP:
- vxlan.Group = net.IP(datum.Value[0:4])
- case nl.IFLA_VXLAN_GROUP6:
- vxlan.Group = net.IP(datum.Value[0:16])
- case nl.IFLA_VXLAN_TTL:
- vxlan.TTL = int(datum.Value[0])
- case nl.IFLA_VXLAN_TOS:
- vxlan.TOS = int(datum.Value[0])
- case nl.IFLA_VXLAN_LEARNING:
- vxlan.Learning = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_PROXY:
- vxlan.Proxy = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_RSC:
- vxlan.RSC = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_L2MISS:
- vxlan.L2miss = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_L3MISS:
- vxlan.L3miss = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_UDP_CSUM:
- vxlan.UDPCSum = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_TX:
- vxlan.UDP6ZeroCSumTx = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_UDP_ZERO_CSUM6_RX:
- vxlan.UDP6ZeroCSumRx = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_GBP:
- vxlan.GBP = true
- case nl.IFLA_VXLAN_FLOWBASED:
- vxlan.FlowBased = int8(datum.Value[0]) != 0
- case nl.IFLA_VXLAN_AGEING:
- vxlan.Age = int(native.Uint32(datum.Value[0:4]))
- vxlan.NoAge = vxlan.Age == 0
- case nl.IFLA_VXLAN_LIMIT:
- vxlan.Limit = int(native.Uint32(datum.Value[0:4]))
- case nl.IFLA_VXLAN_PORT:
- vxlan.Port = int(ntohs(datum.Value[0:2]))
- case nl.IFLA_VXLAN_PORT_RANGE:
- buf := bytes.NewBuffer(datum.Value[0:4])
- var pr vxlanPortRange
- if binary.Read(buf, binary.BigEndian, &pr) != nil {
- vxlan.PortLow = int(pr.Lo)
- vxlan.PortHigh = int(pr.Hi)
- }
- }
- }
- }
- func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
- bond := link.(*Bond)
- for i := range data {
- switch data[i].Attr.Type {
- case nl.IFLA_BOND_MODE:
- bond.Mode = BondMode(data[i].Value[0])
- case nl.IFLA_BOND_ACTIVE_SLAVE:
- bond.ActiveSlave = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_MIIMON:
- bond.Miimon = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_UPDELAY:
- bond.UpDelay = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_DOWNDELAY:
- bond.DownDelay = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_USE_CARRIER:
- bond.UseCarrier = int(data[i].Value[0])
- case nl.IFLA_BOND_ARP_INTERVAL:
- bond.ArpInterval = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_ARP_IP_TARGET:
- bond.ArpIpTargets = parseBondArpIpTargets(data[i].Value)
- case nl.IFLA_BOND_ARP_VALIDATE:
- bond.ArpValidate = BondArpValidate(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_ARP_ALL_TARGETS:
- bond.ArpAllTargets = BondArpAllTargets(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_PRIMARY:
- bond.Primary = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_PRIMARY_RESELECT:
- bond.PrimaryReselect = BondPrimaryReselect(data[i].Value[0])
- case nl.IFLA_BOND_FAIL_OVER_MAC:
- bond.FailOverMac = BondFailOverMac(data[i].Value[0])
- case nl.IFLA_BOND_XMIT_HASH_POLICY:
- bond.XmitHashPolicy = BondXmitHashPolicy(data[i].Value[0])
- case nl.IFLA_BOND_RESEND_IGMP:
- bond.ResendIgmp = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_NUM_PEER_NOTIF:
- bond.NumPeerNotif = int(data[i].Value[0])
- case nl.IFLA_BOND_ALL_SLAVES_ACTIVE:
- bond.AllSlavesActive = int(data[i].Value[0])
- case nl.IFLA_BOND_MIN_LINKS:
- bond.MinLinks = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_LP_INTERVAL:
- bond.LpInterval = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_PACKETS_PER_SLAVE:
- bond.PacketsPerSlave = int(native.Uint32(data[i].Value[0:4]))
- case nl.IFLA_BOND_AD_LACP_RATE:
- bond.LacpRate = BondLacpRate(data[i].Value[0])
- case nl.IFLA_BOND_AD_SELECT:
- bond.AdSelect = BondAdSelect(data[i].Value[0])
- case nl.IFLA_BOND_AD_INFO:
- // TODO: implement
- case nl.IFLA_BOND_AD_ACTOR_SYS_PRIO:
- bond.AdActorSysPrio = int(native.Uint16(data[i].Value[0:2]))
- case nl.IFLA_BOND_AD_USER_PORT_KEY:
- bond.AdUserPortKey = int(native.Uint16(data[i].Value[0:2]))
- case nl.IFLA_BOND_AD_ACTOR_SYSTEM:
- bond.AdActorSystem = net.HardwareAddr(data[i].Value[0:6])
- case nl.IFLA_BOND_TLB_DYNAMIC_LB:
- bond.TlbDynamicLb = int(data[i].Value[0])
- }
- }
- }
- func parseBondArpIpTargets(value []byte) []net.IP {
- data, err := nl.ParseRouteAttr(value)
- if err != nil {
- return nil
- }
- targets := []net.IP{}
- for i := range data {
- target := net.IP(data[i].Value)
- if ip := target.To4(); ip != nil {
- targets = append(targets, ip)
- continue
- }
- if ip := target.To16(); ip != nil {
- targets = append(targets, ip)
- }
- }
- return targets
- }
- func addBondSlaveAttrs(bondSlave *BondSlave, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_STATE, nl.Uint8Attr(uint8(bondSlave.State)))
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_MII_STATUS, nl.Uint8Attr(uint8(bondSlave.MiiStatus)))
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, nl.Uint32Attr(bondSlave.LinkFailureCount))
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(bondSlave.QueueId))
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, nl.Uint16Attr(bondSlave.AggregatorId))
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, nl.Uint8Attr(bondSlave.AdActorOperPortState))
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, nl.Uint16Attr(bondSlave.AdPartnerOperPortState))
- if mac := bondSlave.PermHardwareAddr; mac != nil {
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_PERM_HWADDR, []byte(mac))
- }
- }
- func parseBondSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
- bondSlave := slave.(*BondSlave)
- for i := range data {
- switch data[i].Attr.Type {
- case nl.IFLA_BOND_SLAVE_STATE:
- bondSlave.State = BondSlaveState(data[i].Value[0])
- case nl.IFLA_BOND_SLAVE_MII_STATUS:
- bondSlave.MiiStatus = BondSlaveMiiStatus(data[i].Value[0])
- case nl.IFLA_BOND_SLAVE_LINK_FAILURE_COUNT:
- bondSlave.LinkFailureCount = native.Uint32(data[i].Value[0:4])
- case nl.IFLA_BOND_SLAVE_PERM_HWADDR:
- bondSlave.PermHardwareAddr = net.HardwareAddr(data[i].Value[0:6])
- case nl.IFLA_BOND_SLAVE_QUEUE_ID:
- bondSlave.QueueId = native.Uint16(data[i].Value[0:2])
- case nl.IFLA_BOND_SLAVE_AD_AGGREGATOR_ID:
- bondSlave.AggregatorId = native.Uint16(data[i].Value[0:2])
- case nl.IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE:
- bondSlave.AdActorOperPortState = uint8(data[i].Value[0])
- case nl.IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE:
- bondSlave.AdPartnerOperPortState = native.Uint16(data[i].Value[0:2])
- }
- }
- }
- func parseVrfSlaveData(slave LinkSlave, data []syscall.NetlinkRouteAttr) {
- vrfSlave := slave.(*VrfSlave)
- for i := range data {
- switch data[i].Attr.Type {
- case nl.IFLA_BOND_SLAVE_STATE:
- vrfSlave.Table = native.Uint32(data[i].Value[0:4])
- }
- }
- }
- func parseIPVlanData(link Link, data []syscall.NetlinkRouteAttr) {
- ipv := link.(*IPVlan)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_IPVLAN_MODE:
- ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
- case nl.IFLA_IPVLAN_FLAG:
- ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
- }
- }
- }
- func parseIPVtapData(link Link, data []syscall.NetlinkRouteAttr) {
- ipv := link.(*IPVtap)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_IPVLAN_MODE:
- ipv.Mode = IPVlanMode(native.Uint32(datum.Value[0:4]))
- case nl.IFLA_IPVLAN_FLAG:
- ipv.Flag = IPVlanFlag(native.Uint32(datum.Value[0:4]))
- }
- }
- }
- func parseMacvtapData(link Link, data []syscall.NetlinkRouteAttr) {
- macv := link.(*Macvtap)
- parseMacvlanData(&macv.Macvlan, data)
- }
- func parseMacvlanData(link Link, data []syscall.NetlinkRouteAttr) {
- macv := link.(*Macvlan)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_MACVLAN_MODE:
- switch native.Uint32(datum.Value[0:4]) {
- case nl.MACVLAN_MODE_PRIVATE:
- macv.Mode = MACVLAN_MODE_PRIVATE
- case nl.MACVLAN_MODE_VEPA:
- macv.Mode = MACVLAN_MODE_VEPA
- case nl.MACVLAN_MODE_BRIDGE:
- macv.Mode = MACVLAN_MODE_BRIDGE
- case nl.MACVLAN_MODE_PASSTHRU:
- macv.Mode = MACVLAN_MODE_PASSTHRU
- case nl.MACVLAN_MODE_SOURCE:
- macv.Mode = MACVLAN_MODE_SOURCE
- }
- case nl.IFLA_MACVLAN_MACADDR_COUNT:
- macv.MACAddrs = make([]net.HardwareAddr, 0, int(native.Uint32(datum.Value[0:4])))
- case nl.IFLA_MACVLAN_MACADDR_DATA:
- macs, err := nl.ParseRouteAttr(datum.Value[:])
- if err != nil {
- panic(fmt.Sprintf("failed to ParseRouteAttr for IFLA_MACVLAN_MACADDR_DATA: %v", err))
- }
- for _, macDatum := range macs {
- macv.MACAddrs = append(macv.MACAddrs, net.HardwareAddr(macDatum.Value[0:6]))
- }
- }
- }
- }
- // copied from pkg/net_linux.go
- func linkFlags(rawFlags uint32) net.Flags {
- var f net.Flags
- if rawFlags&unix.IFF_UP != 0 {
- f |= net.FlagUp
- }
- if rawFlags&unix.IFF_BROADCAST != 0 {
- f |= net.FlagBroadcast
- }
- if rawFlags&unix.IFF_LOOPBACK != 0 {
- f |= net.FlagLoopback
- }
- if rawFlags&unix.IFF_POINTOPOINT != 0 {
- f |= net.FlagPointToPoint
- }
- if rawFlags&unix.IFF_MULTICAST != 0 {
- f |= net.FlagMulticast
- }
- return f
- }
- func addGeneveAttrs(geneve *Geneve, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if geneve.FlowBased {
- // In flow based mode, no other attributes need to be configured
- linkInfo.AddRtAttr(nl.IFLA_GENEVE_COLLECT_METADATA, boolAttr(geneve.FlowBased))
- return
- }
- if ip := geneve.Remote; ip != nil {
- if ip4 := ip.To4(); ip4 != nil {
- data.AddRtAttr(nl.IFLA_GENEVE_REMOTE, ip.To4())
- } else {
- data.AddRtAttr(nl.IFLA_GENEVE_REMOTE6, []byte(ip))
- }
- }
- if geneve.ID != 0 {
- data.AddRtAttr(nl.IFLA_GENEVE_ID, nl.Uint32Attr(geneve.ID))
- }
- if geneve.Dport != 0 {
- data.AddRtAttr(nl.IFLA_GENEVE_PORT, htons(geneve.Dport))
- }
- if geneve.Ttl != 0 {
- data.AddRtAttr(nl.IFLA_GENEVE_TTL, nl.Uint8Attr(geneve.Ttl))
- }
- if geneve.Tos != 0 {
- data.AddRtAttr(nl.IFLA_GENEVE_TOS, nl.Uint8Attr(geneve.Tos))
- }
- }
- func parseGeneveData(link Link, data []syscall.NetlinkRouteAttr) {
- geneve := link.(*Geneve)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_GENEVE_ID:
- geneve.ID = native.Uint32(datum.Value[0:4])
- case nl.IFLA_GENEVE_REMOTE, nl.IFLA_GENEVE_REMOTE6:
- geneve.Remote = datum.Value
- case nl.IFLA_GENEVE_PORT:
- geneve.Dport = ntohs(datum.Value[0:2])
- case nl.IFLA_GENEVE_TTL:
- geneve.Ttl = uint8(datum.Value[0])
- case nl.IFLA_GENEVE_TOS:
- geneve.Tos = uint8(datum.Value[0])
- }
- }
- }
- func addGretapAttrs(gretap *Gretap, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if gretap.FlowBased {
- // In flow based mode, no other attributes need to be configured
- data.AddRtAttr(nl.IFLA_GRE_COLLECT_METADATA, boolAttr(gretap.FlowBased))
- return
- }
- if ip := gretap.Local; ip != nil {
- if ip.To4() != nil {
- ip = ip.To4()
- }
- data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip))
- }
- if ip := gretap.Remote; ip != nil {
- if ip.To4() != nil {
- ip = ip.To4()
- }
- data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip))
- }
- if gretap.IKey != 0 {
- data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gretap.IKey))
- gretap.IFlags |= uint16(nl.GRE_KEY)
- }
- if gretap.OKey != 0 {
- data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gretap.OKey))
- gretap.OFlags |= uint16(nl.GRE_KEY)
- }
- data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gretap.IFlags))
- data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gretap.OFlags))
- if gretap.Link != 0 {
- data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gretap.Link))
- }
- data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gretap.PMtuDisc))
- data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gretap.Ttl))
- data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gretap.Tos))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gretap.EncapType))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gretap.EncapFlags))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gretap.EncapSport))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gretap.EncapDport))
- }
- func parseGretapData(link Link, data []syscall.NetlinkRouteAttr) {
- gre := link.(*Gretap)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_GRE_OKEY:
- gre.IKey = ntohl(datum.Value[0:4])
- case nl.IFLA_GRE_IKEY:
- gre.OKey = ntohl(datum.Value[0:4])
- case nl.IFLA_GRE_LOCAL:
- gre.Local = net.IP(datum.Value)
- case nl.IFLA_GRE_REMOTE:
- gre.Remote = net.IP(datum.Value)
- case nl.IFLA_GRE_ENCAP_SPORT:
- gre.EncapSport = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_ENCAP_DPORT:
- gre.EncapDport = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_IFLAGS:
- gre.IFlags = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_OFLAGS:
- gre.OFlags = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_TTL:
- gre.Ttl = uint8(datum.Value[0])
- case nl.IFLA_GRE_TOS:
- gre.Tos = uint8(datum.Value[0])
- case nl.IFLA_GRE_PMTUDISC:
- gre.PMtuDisc = uint8(datum.Value[0])
- case nl.IFLA_GRE_ENCAP_TYPE:
- gre.EncapType = native.Uint16(datum.Value[0:2])
- case nl.IFLA_GRE_ENCAP_FLAGS:
- gre.EncapFlags = native.Uint16(datum.Value[0:2])
- case nl.IFLA_GRE_COLLECT_METADATA:
- gre.FlowBased = true
- }
- }
- }
- func addGretunAttrs(gre *Gretun, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if ip := gre.Local; ip != nil {
- if ip.To4() != nil {
- ip = ip.To4()
- }
- data.AddRtAttr(nl.IFLA_GRE_LOCAL, []byte(ip))
- }
- if ip := gre.Remote; ip != nil {
- if ip.To4() != nil {
- ip = ip.To4()
- }
- data.AddRtAttr(nl.IFLA_GRE_REMOTE, []byte(ip))
- }
- if gre.IKey != 0 {
- data.AddRtAttr(nl.IFLA_GRE_IKEY, htonl(gre.IKey))
- gre.IFlags |= uint16(nl.GRE_KEY)
- }
- if gre.OKey != 0 {
- data.AddRtAttr(nl.IFLA_GRE_OKEY, htonl(gre.OKey))
- gre.OFlags |= uint16(nl.GRE_KEY)
- }
- data.AddRtAttr(nl.IFLA_GRE_IFLAGS, htons(gre.IFlags))
- data.AddRtAttr(nl.IFLA_GRE_OFLAGS, htons(gre.OFlags))
- if gre.Link != 0 {
- data.AddRtAttr(nl.IFLA_GRE_LINK, nl.Uint32Attr(gre.Link))
- }
- data.AddRtAttr(nl.IFLA_GRE_PMTUDISC, nl.Uint8Attr(gre.PMtuDisc))
- data.AddRtAttr(nl.IFLA_GRE_TTL, nl.Uint8Attr(gre.Ttl))
- data.AddRtAttr(nl.IFLA_GRE_TOS, nl.Uint8Attr(gre.Tos))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_TYPE, nl.Uint16Attr(gre.EncapType))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_FLAGS, nl.Uint16Attr(gre.EncapFlags))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_SPORT, htons(gre.EncapSport))
- data.AddRtAttr(nl.IFLA_GRE_ENCAP_DPORT, htons(gre.EncapDport))
- }
- func parseGretunData(link Link, data []syscall.NetlinkRouteAttr) {
- gre := link.(*Gretun)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_GRE_IKEY:
- gre.IKey = ntohl(datum.Value[0:4])
- case nl.IFLA_GRE_OKEY:
- gre.OKey = ntohl(datum.Value[0:4])
- case nl.IFLA_GRE_LOCAL:
- gre.Local = net.IP(datum.Value)
- case nl.IFLA_GRE_REMOTE:
- gre.Remote = net.IP(datum.Value)
- case nl.IFLA_GRE_IFLAGS:
- gre.IFlags = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_OFLAGS:
- gre.OFlags = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_TTL:
- gre.Ttl = uint8(datum.Value[0])
- case nl.IFLA_GRE_TOS:
- gre.Tos = uint8(datum.Value[0])
- case nl.IFLA_GRE_PMTUDISC:
- gre.PMtuDisc = uint8(datum.Value[0])
- case nl.IFLA_GRE_ENCAP_TYPE:
- gre.EncapType = native.Uint16(datum.Value[0:2])
- case nl.IFLA_GRE_ENCAP_FLAGS:
- gre.EncapFlags = native.Uint16(datum.Value[0:2])
- case nl.IFLA_GRE_ENCAP_SPORT:
- gre.EncapSport = ntohs(datum.Value[0:2])
- case nl.IFLA_GRE_ENCAP_DPORT:
- gre.EncapDport = ntohs(datum.Value[0:2])
- }
- }
- }
- func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
- attrs := nl.NewRtAttr(unix.IFLA_XDP|unix.NLA_F_NESTED, nil)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(xdp.Fd))
- attrs.AddRtAttr(nl.IFLA_XDP_FD, b)
- if xdp.Flags != 0 {
- b := make([]byte, 4)
- native.PutUint32(b, xdp.Flags)
- attrs.AddRtAttr(nl.IFLA_XDP_FLAGS, b)
- }
- req.AddData(attrs)
- }
- func parseLinkXdp(data []byte) (*LinkXdp, error) {
- attrs, err := nl.ParseRouteAttr(data)
- if err != nil {
- return nil, err
- }
- xdp := &LinkXdp{}
- for _, attr := range attrs {
- switch attr.Attr.Type {
- case nl.IFLA_XDP_FD:
- xdp.Fd = int(native.Uint32(attr.Value[0:4]))
- case nl.IFLA_XDP_ATTACHED:
- xdp.AttachMode = uint32(attr.Value[0])
- xdp.Attached = xdp.AttachMode != 0
- case nl.IFLA_XDP_FLAGS:
- xdp.Flags = native.Uint32(attr.Value[0:4])
- case nl.IFLA_XDP_PROG_ID:
- xdp.ProgId = native.Uint32(attr.Value[0:4])
- }
- }
- return xdp, nil
- }
- func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
- if iptun.FlowBased {
- // In flow based mode, no other attributes need to be configured
- linkInfo.AddRtAttr(nl.IFLA_IPTUN_COLLECT_METADATA, boolAttr(iptun.FlowBased))
- return
- }
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- ip := iptun.Local.To4()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
- }
- ip = iptun.Remote.To4()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
- }
- if iptun.Link != 0 {
- data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link))
- }
- data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc))
- data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl))
- data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(iptun.EncapType))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(iptun.EncapFlags))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(iptun.EncapSport))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(iptun.EncapDport))
- data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(iptun.Proto))
- }
- func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
- iptun := link.(*Iptun)
- for _, datum := range data {
- // NOTE: same with vxlan, ip tunnel may also has null datum.Value
- if len(datum.Value) == 0 {
- continue
- }
- switch datum.Attr.Type {
- case nl.IFLA_IPTUN_LOCAL:
- iptun.Local = net.IP(datum.Value[0:4])
- case nl.IFLA_IPTUN_REMOTE:
- iptun.Remote = net.IP(datum.Value[0:4])
- case nl.IFLA_IPTUN_TTL:
- iptun.Ttl = uint8(datum.Value[0])
- case nl.IFLA_IPTUN_TOS:
- iptun.Tos = uint8(datum.Value[0])
- case nl.IFLA_IPTUN_PMTUDISC:
- iptun.PMtuDisc = uint8(datum.Value[0])
- case nl.IFLA_IPTUN_ENCAP_SPORT:
- iptun.EncapSport = ntohs(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_DPORT:
- iptun.EncapDport = ntohs(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_TYPE:
- iptun.EncapType = native.Uint16(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_FLAGS:
- iptun.EncapFlags = native.Uint16(datum.Value[0:2])
- case nl.IFLA_IPTUN_COLLECT_METADATA:
- iptun.FlowBased = true
- case nl.IFLA_IPTUN_PROTO:
- iptun.Proto = datum.Value[0]
- }
- }
- }
- func addIp6tnlAttrs(ip6tnl *Ip6tnl, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if ip6tnl.Link != 0 {
- data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(ip6tnl.Link))
- }
- ip := ip6tnl.Local.To16()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
- }
- ip = ip6tnl.Remote.To16()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
- }
- data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(ip6tnl.Ttl))
- data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(ip6tnl.Tos))
- data.AddRtAttr(nl.IFLA_IPTUN_FLAGS, nl.Uint32Attr(ip6tnl.Flags))
- data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(ip6tnl.Proto))
- data.AddRtAttr(nl.IFLA_IPTUN_FLOWINFO, nl.Uint32Attr(ip6tnl.FlowInfo))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(ip6tnl.EncapLimit))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(ip6tnl.EncapType))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(ip6tnl.EncapFlags))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(ip6tnl.EncapSport))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(ip6tnl.EncapDport))
- }
- func parseIp6tnlData(link Link, data []syscall.NetlinkRouteAttr) {
- ip6tnl := link.(*Ip6tnl)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_IPTUN_LOCAL:
- ip6tnl.Local = net.IP(datum.Value[:16])
- case nl.IFLA_IPTUN_REMOTE:
- ip6tnl.Remote = net.IP(datum.Value[:16])
- case nl.IFLA_IPTUN_TTL:
- ip6tnl.Ttl = datum.Value[0]
- case nl.IFLA_IPTUN_TOS:
- ip6tnl.Tos = datum.Value[0]
- case nl.IFLA_IPTUN_FLAGS:
- ip6tnl.Flags = native.Uint32(datum.Value[:4])
- case nl.IFLA_IPTUN_PROTO:
- ip6tnl.Proto = datum.Value[0]
- case nl.IFLA_IPTUN_FLOWINFO:
- ip6tnl.FlowInfo = native.Uint32(datum.Value[:4])
- case nl.IFLA_IPTUN_ENCAP_LIMIT:
- ip6tnl.EncapLimit = datum.Value[0]
- case nl.IFLA_IPTUN_ENCAP_TYPE:
- ip6tnl.EncapType = native.Uint16(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_FLAGS:
- ip6tnl.EncapFlags = native.Uint16(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_SPORT:
- ip6tnl.EncapSport = ntohs(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_DPORT:
- ip6tnl.EncapDport = ntohs(datum.Value[0:2])
- }
- }
- }
- func addSittunAttrs(sittun *Sittun, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if sittun.Link != 0 {
- data.AddRtAttr(nl.IFLA_IPTUN_LINK, nl.Uint32Attr(sittun.Link))
- }
- ip := sittun.Local.To4()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_IPTUN_LOCAL, []byte(ip))
- }
- ip = sittun.Remote.To4()
- if ip != nil {
- data.AddRtAttr(nl.IFLA_IPTUN_REMOTE, []byte(ip))
- }
- if sittun.Ttl > 0 {
- // Would otherwise fail on 3.10 kernel
- data.AddRtAttr(nl.IFLA_IPTUN_TTL, nl.Uint8Attr(sittun.Ttl))
- }
- data.AddRtAttr(nl.IFLA_IPTUN_PROTO, nl.Uint8Attr(sittun.Proto))
- data.AddRtAttr(nl.IFLA_IPTUN_TOS, nl.Uint8Attr(sittun.Tos))
- data.AddRtAttr(nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(sittun.PMtuDisc))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_LIMIT, nl.Uint8Attr(sittun.EncapLimit))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_TYPE, nl.Uint16Attr(sittun.EncapType))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_FLAGS, nl.Uint16Attr(sittun.EncapFlags))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_SPORT, htons(sittun.EncapSport))
- data.AddRtAttr(nl.IFLA_IPTUN_ENCAP_DPORT, htons(sittun.EncapDport))
- }
- func parseSittunData(link Link, data []syscall.NetlinkRouteAttr) {
- sittun := link.(*Sittun)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_IPTUN_LOCAL:
- sittun.Local = net.IP(datum.Value[0:4])
- case nl.IFLA_IPTUN_REMOTE:
- sittun.Remote = net.IP(datum.Value[0:4])
- case nl.IFLA_IPTUN_TTL:
- sittun.Ttl = datum.Value[0]
- case nl.IFLA_IPTUN_TOS:
- sittun.Tos = datum.Value[0]
- case nl.IFLA_IPTUN_PMTUDISC:
- sittun.PMtuDisc = datum.Value[0]
- case nl.IFLA_IPTUN_PROTO:
- sittun.Proto = datum.Value[0]
- case nl.IFLA_IPTUN_ENCAP_TYPE:
- sittun.EncapType = native.Uint16(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_FLAGS:
- sittun.EncapFlags = native.Uint16(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_SPORT:
- sittun.EncapSport = ntohs(datum.Value[0:2])
- case nl.IFLA_IPTUN_ENCAP_DPORT:
- sittun.EncapDport = ntohs(datum.Value[0:2])
- }
- }
- }
- func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- family := FAMILY_V4
- if vti.Local.To4() == nil {
- family = FAMILY_V6
- }
- var ip net.IP
- if family == FAMILY_V4 {
- ip = vti.Local.To4()
- } else {
- ip = vti.Local
- }
- if ip != nil {
- data.AddRtAttr(nl.IFLA_VTI_LOCAL, []byte(ip))
- }
- if family == FAMILY_V4 {
- ip = vti.Remote.To4()
- } else {
- ip = vti.Remote
- }
- if ip != nil {
- data.AddRtAttr(nl.IFLA_VTI_REMOTE, []byte(ip))
- }
- if vti.Link != 0 {
- data.AddRtAttr(nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link))
- }
- data.AddRtAttr(nl.IFLA_VTI_IKEY, htonl(vti.IKey))
- data.AddRtAttr(nl.IFLA_VTI_OKEY, htonl(vti.OKey))
- }
- func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
- vti := link.(*Vti)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_VTI_LOCAL:
- vti.Local = net.IP(datum.Value)
- case nl.IFLA_VTI_REMOTE:
- vti.Remote = net.IP(datum.Value)
- case nl.IFLA_VTI_IKEY:
- vti.IKey = ntohl(datum.Value[0:4])
- case nl.IFLA_VTI_OKEY:
- vti.OKey = ntohl(datum.Value[0:4])
- }
- }
- }
- func addVrfAttrs(vrf *Vrf, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- b := make([]byte, 4)
- native.PutUint32(b, uint32(vrf.Table))
- data.AddRtAttr(nl.IFLA_VRF_TABLE, b)
- }
- func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
- vrf := link.(*Vrf)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_VRF_TABLE:
- vrf.Table = native.Uint32(datum.Value[0:4])
- }
- }
- }
- func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- if bridge.MulticastSnooping != nil {
- data.AddRtAttr(nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping))
- }
- if bridge.AgeingTime != nil {
- data.AddRtAttr(nl.IFLA_BR_AGEING_TIME, nl.Uint32Attr(*bridge.AgeingTime))
- }
- if bridge.HelloTime != nil {
- data.AddRtAttr(nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime))
- }
- if bridge.VlanFiltering != nil {
- data.AddRtAttr(nl.IFLA_BR_VLAN_FILTERING, boolToByte(*bridge.VlanFiltering))
- }
- }
- func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
- br := bridge.(*Bridge)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_BR_AGEING_TIME:
- ageingTime := native.Uint32(datum.Value[0:4])
- br.AgeingTime = &ageingTime
- case nl.IFLA_BR_HELLO_TIME:
- helloTime := native.Uint32(datum.Value[0:4])
- br.HelloTime = &helloTime
- case nl.IFLA_BR_MCAST_SNOOPING:
- mcastSnooping := datum.Value[0] == 1
- br.MulticastSnooping = &mcastSnooping
- case nl.IFLA_BR_VLAN_FILTERING:
- vlanFiltering := datum.Value[0] == 1
- br.VlanFiltering = &vlanFiltering
- }
- }
- }
- func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0)))
- data.AddRtAttr(nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1)))
- data.AddRtAttr(nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072))
- if gtp.Role != nl.GTP_ROLE_GGSN {
- data.AddRtAttr(nl.IFLA_GTP_ROLE, nl.Uint32Attr(uint32(gtp.Role)))
- }
- }
- func parseGTPData(link Link, data []syscall.NetlinkRouteAttr) {
- gtp := link.(*GTP)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_GTP_FD0:
- gtp.FD0 = int(native.Uint32(datum.Value))
- case nl.IFLA_GTP_FD1:
- gtp.FD1 = int(native.Uint32(datum.Value))
- case nl.IFLA_GTP_PDP_HASHSIZE:
- gtp.PDPHashsize = int(native.Uint32(datum.Value))
- case nl.IFLA_GTP_ROLE:
- gtp.Role = int(native.Uint32(datum.Value))
- }
- }
- }
- func parseVfInfoList(data []syscall.NetlinkRouteAttr) ([]VfInfo, error) {
- var vfs []VfInfo
- for i, element := range data {
- if element.Attr.Type != nl.IFLA_VF_INFO {
- return nil, fmt.Errorf("Incorrect element type in vf info list: %d", element.Attr.Type)
- }
- vfAttrs, err := nl.ParseRouteAttr(element.Value)
- if err != nil {
- return nil, err
- }
- vfs = append(vfs, parseVfInfo(vfAttrs, i))
- }
- return vfs, nil
- }
- func parseVfInfo(data []syscall.NetlinkRouteAttr, id int) VfInfo {
- vf := VfInfo{ID: id}
- for _, element := range data {
- switch element.Attr.Type {
- case nl.IFLA_VF_MAC:
- mac := nl.DeserializeVfMac(element.Value[:])
- vf.Mac = mac.Mac[:6]
- case nl.IFLA_VF_VLAN:
- vl := nl.DeserializeVfVlan(element.Value[:])
- vf.Vlan = int(vl.Vlan)
- vf.Qos = int(vl.Qos)
- case nl.IFLA_VF_TX_RATE:
- txr := nl.DeserializeVfTxRate(element.Value[:])
- vf.TxRate = int(txr.Rate)
- case nl.IFLA_VF_SPOOFCHK:
- sp := nl.DeserializeVfSpoofchk(element.Value[:])
- vf.Spoofchk = sp.Setting != 0
- case nl.IFLA_VF_LINK_STATE:
- ls := nl.DeserializeVfLinkState(element.Value[:])
- vf.LinkState = ls.LinkState
- case nl.IFLA_VF_RATE:
- vfr := nl.DeserializeVfRate(element.Value[:])
- vf.MaxTxRate = vfr.MaxTxRate
- vf.MinTxRate = vfr.MinTxRate
- case nl.IFLA_VF_STATS:
- vfstats := nl.DeserializeVfStats(element.Value[:])
- vf.RxPackets = vfstats.RxPackets
- vf.TxPackets = vfstats.TxPackets
- vf.RxBytes = vfstats.RxBytes
- vf.TxBytes = vfstats.TxBytes
- vf.Multicast = vfstats.Multicast
- vf.Broadcast = vfstats.Broadcast
- vf.RxDropped = vfstats.RxDropped
- vf.TxDropped = vfstats.TxDropped
- case nl.IFLA_VF_RSS_QUERY_EN:
- result := nl.DeserializeVfRssQueryEn(element.Value)
- vf.RssQuery = result.Setting
- case nl.IFLA_VF_TRUST:
- result := nl.DeserializeVfTrust(element.Value)
- vf.Trust = result.Setting
- }
- }
- return vf
- }
- func addXfrmiAttrs(xfrmi *Xfrmi, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_XFRM_LINK, nl.Uint32Attr(uint32(xfrmi.ParentIndex)))
- if xfrmi.Ifid != 0 {
- data.AddRtAttr(nl.IFLA_XFRM_IF_ID, nl.Uint32Attr(xfrmi.Ifid))
- }
- }
- func parseXfrmiData(link Link, data []syscall.NetlinkRouteAttr) {
- xfrmi := link.(*Xfrmi)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_XFRM_LINK:
- xfrmi.ParentIndex = int(native.Uint32(datum.Value))
- case nl.IFLA_XFRM_IF_ID:
- xfrmi.Ifid = native.Uint32(datum.Value)
- }
- }
- }
- // LinkSetBondSlave add slave to bond link via ioctl interface.
- func LinkSetBondSlave(link Link, master *Bond) error {
- fd, err := getSocketUDP()
- if err != nil {
- return err
- }
- defer syscall.Close(fd)
- ifreq := newIocltSlaveReq(link.Attrs().Name, master.Attrs().Name)
- _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), unix.SIOCBONDENSLAVE, uintptr(unsafe.Pointer(ifreq)))
- if errno != 0 {
- return fmt.Errorf("Failed to enslave %q to %q, errno=%v", link.Attrs().Name, master.Attrs().Name, errno)
- }
- return nil
- }
- // LinkSetBondSlaveQueueId modify bond slave queue-id.
- func (h *Handle) LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
- base := link.Attrs()
- h.ensureIndex(base)
- req := h.newNetlinkRequest(unix.RTM_SETLINK, unix.NLM_F_ACK)
- msg := nl.NewIfInfomsg(unix.AF_UNSPEC)
- msg.Index = int32(base.Index)
- req.AddData(msg)
- linkInfo := nl.NewRtAttr(unix.IFLA_LINKINFO, nil)
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_SLAVE_DATA, nil)
- data.AddRtAttr(nl.IFLA_BOND_SLAVE_QUEUE_ID, nl.Uint16Attr(queueId))
- req.AddData(linkInfo)
- _, err := req.Execute(unix.NETLINK_ROUTE, 0)
- return err
- }
- // LinkSetBondSlaveQueueId modify bond slave queue-id.
- func LinkSetBondSlaveQueueId(link Link, queueId uint16) error {
- return pkgHandle.LinkSetBondSlaveQueueId(link, queueId)
- }
- func vethStatsSerialize(stats ethtoolStats) ([]byte, error) {
- statsSize := int(unsafe.Sizeof(stats)) + int(stats.nStats)*int(unsafe.Sizeof(uint64(0)))
- b := make([]byte, 0, statsSize)
- buf := bytes.NewBuffer(b)
- err := binary.Write(buf, nl.NativeEndian(), stats)
- return buf.Bytes()[:statsSize], err
- }
- type vethEthtoolStats struct {
- Cmd uint32
- NStats uint32
- Peer uint64
- // Newer kernels have XDP stats in here, but we only care
- // to extract the peer ifindex here.
- }
- func vethStatsDeserialize(b []byte) (vethEthtoolStats, error) {
- var stats = vethEthtoolStats{}
- err := binary.Read(bytes.NewReader(b), nl.NativeEndian(), &stats)
- return stats, err
- }
- // VethPeerIndex get veth peer index.
- func VethPeerIndex(link *Veth) (int, error) {
- fd, err := getSocketUDP()
- if err != nil {
- return -1, err
- }
- defer syscall.Close(fd)
- ifreq, sSet := newIocltStringSetReq(link.Name)
- _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
- if errno != 0 {
- return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
- }
- stats := ethtoolStats{
- cmd: ETHTOOL_GSTATS,
- nStats: sSet.data[0],
- }
- buffer, err := vethStatsSerialize(stats)
- if err != nil {
- return -1, err
- }
- ifreq.Data = uintptr(unsafe.Pointer(&buffer[0]))
- _, _, errno = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), SIOCETHTOOL, uintptr(unsafe.Pointer(ifreq)))
- if errno != 0 {
- return -1, fmt.Errorf("SIOCETHTOOL request for %q failed, errno=%v", link.Attrs().Name, errno)
- }
- vstats, err := vethStatsDeserialize(buffer)
- if err != nil {
- return -1, err
- }
- return int(vstats.Peer), nil
- }
- func parseTuntapData(link Link, data []syscall.NetlinkRouteAttr) {
- tuntap := link.(*Tuntap)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_TUN_OWNER:
- tuntap.Owner = native.Uint32(datum.Value)
- case nl.IFLA_TUN_GROUP:
- tuntap.Group = native.Uint32(datum.Value)
- case nl.IFLA_TUN_TYPE:
- tuntap.Mode = TuntapMode(uint8(datum.Value[0]))
- case nl.IFLA_TUN_PERSIST:
- tuntap.NonPersist = false
- if uint8(datum.Value[0]) == 0 {
- tuntap.NonPersist = true
- }
- }
- }
- }
- func parseIPoIBData(link Link, data []syscall.NetlinkRouteAttr) {
- ipoib := link.(*IPoIB)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_IPOIB_PKEY:
- ipoib.Pkey = uint16(native.Uint16(datum.Value))
- case nl.IFLA_IPOIB_MODE:
- ipoib.Mode = IPoIBMode(native.Uint16(datum.Value))
- case nl.IFLA_IPOIB_UMCAST:
- ipoib.Umcast = uint16(native.Uint16(datum.Value))
- }
- }
- }
- func parseCanData(link Link, data []syscall.NetlinkRouteAttr) {
- can := link.(*Can)
- for _, datum := range data {
- switch datum.Attr.Type {
- case nl.IFLA_CAN_BITTIMING:
- can.BitRate = native.Uint32(datum.Value)
- can.SamplePoint = native.Uint32(datum.Value[4:])
- can.TimeQuanta = native.Uint32(datum.Value[8:])
- can.PropagationSegment = native.Uint32(datum.Value[12:])
- can.PhaseSegment1 = native.Uint32(datum.Value[16:])
- can.PhaseSegment2 = native.Uint32(datum.Value[20:])
- can.SyncJumpWidth = native.Uint32(datum.Value[24:])
- can.BitRatePreScaler = native.Uint32(datum.Value[28:])
- case nl.IFLA_CAN_BITTIMING_CONST:
- can.Name = string(datum.Value[:16])
- can.TimeSegment1Min = native.Uint32(datum.Value[16:])
- can.TimeSegment1Max = native.Uint32(datum.Value[20:])
- can.TimeSegment2Min = native.Uint32(datum.Value[24:])
- can.TimeSegment2Max = native.Uint32(datum.Value[28:])
- can.SyncJumpWidthMax = native.Uint32(datum.Value[32:])
- can.BitRatePreScalerMin = native.Uint32(datum.Value[36:])
- can.BitRatePreScalerMax = native.Uint32(datum.Value[40:])
- can.BitRatePreScalerInc = native.Uint32(datum.Value[44:])
- case nl.IFLA_CAN_CLOCK:
- can.ClockFrequency = native.Uint32(datum.Value)
- case nl.IFLA_CAN_STATE:
- can.State = native.Uint32(datum.Value)
- case nl.IFLA_CAN_CTRLMODE:
- can.Mask = native.Uint32(datum.Value)
- can.Flags = native.Uint32(datum.Value[4:])
- case nl.IFLA_CAN_BERR_COUNTER:
- can.TxError = native.Uint16(datum.Value)
- can.RxError = native.Uint16(datum.Value[2:])
- case nl.IFLA_CAN_RESTART_MS:
- can.RestartMs = native.Uint32(datum.Value)
- case nl.IFLA_CAN_DATA_BITTIMING_CONST:
- case nl.IFLA_CAN_RESTART:
- case nl.IFLA_CAN_DATA_BITTIMING:
- case nl.IFLA_CAN_TERMINATION:
- case nl.IFLA_CAN_TERMINATION_CONST:
- case nl.IFLA_CAN_BITRATE_CONST:
- case nl.IFLA_CAN_DATA_BITRATE_CONST:
- case nl.IFLA_CAN_BITRATE_MAX:
- }
- }
- }
- func addIPoIBAttrs(ipoib *IPoIB, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_IPOIB_PKEY, nl.Uint16Attr(uint16(ipoib.Pkey)))
- data.AddRtAttr(nl.IFLA_IPOIB_MODE, nl.Uint16Attr(uint16(ipoib.Mode)))
- data.AddRtAttr(nl.IFLA_IPOIB_UMCAST, nl.Uint16Attr(uint16(ipoib.Umcast)))
- }
- func addBareUDPAttrs(bareudp *BareUDP, linkInfo *nl.RtAttr) {
- data := linkInfo.AddRtAttr(nl.IFLA_INFO_DATA, nil)
- data.AddRtAttr(nl.IFLA_BAREUDP_PORT, nl.Uint16Attr(nl.Swap16(bareudp.Port)))
- data.AddRtAttr(nl.IFLA_BAREUDP_ETHERTYPE, nl.Uint16Attr(nl.Swap16(bareudp.EtherType)))
- if bareudp.SrcPortMin != 0 {
- data.AddRtAttr(nl.IFLA_BAREUDP_SRCPORT_MIN, nl.Uint16Attr(bareudp.SrcPortMin))
- }
- if bareudp.MultiProto {
- data.AddRtAttr(nl.IFLA_BAREUDP_MULTIPROTO_MODE, []byte{})
- }
- }
- func parseBareUDPData(link Link, data []syscall.NetlinkRouteAttr) {
- bareudp := link.(*BareUDP)
- for _, attr := range data {
- switch attr.Attr.Type {
- case nl.IFLA_BAREUDP_PORT:
- bareudp.Port = binary.BigEndian.Uint16(attr.Value)
- case nl.IFLA_BAREUDP_ETHERTYPE:
- bareudp.EtherType = binary.BigEndian.Uint16(attr.Value)
- case nl.IFLA_BAREUDP_SRCPORT_MIN:
- bareudp.SrcPortMin = native.Uint16(attr.Value)
- case nl.IFLA_BAREUDP_MULTIPROTO_MODE:
- bareudp.MultiProto = true
- }
- }
- }
|