|
@@ -103,7 +103,7 @@ func (h *Handle) SetPromiscOn(link Link) error {
|
|
|
|
|
|
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
msg.Change = syscall.IFF_PROMISC
|
|
msg.Change = syscall.IFF_PROMISC
|
|
- msg.Flags = syscall.IFF_UP
|
|
|
|
|
|
+ msg.Flags = syscall.IFF_PROMISC
|
|
msg.Index = int32(base.Index)
|
|
msg.Index = int32(base.Index)
|
|
req.AddData(msg)
|
|
req.AddData(msg)
|
|
|
|
|
|
@@ -111,6 +111,16 @@ func (h *Handle) SetPromiscOn(link Link) error {
|
|
return err
|
|
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, syscall.NLM_F_ACK)
|
|
|
|
+}
|
|
|
|
+
|
|
func SetPromiscOn(link Link) error {
|
|
func SetPromiscOn(link Link) error {
|
|
return pkgHandle.SetPromiscOn(link)
|
|
return pkgHandle.SetPromiscOn(link)
|
|
}
|
|
}
|
|
@@ -122,7 +132,7 @@ func (h *Handle) SetPromiscOff(link Link) error {
|
|
|
|
|
|
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
msg.Change = syscall.IFF_PROMISC
|
|
msg.Change = syscall.IFF_PROMISC
|
|
- msg.Flags = 0 & ^syscall.IFF_UP
|
|
|
|
|
|
+ msg.Flags = 0 & ^syscall.IFF_PROMISC
|
|
msg.Index = int32(base.Index)
|
|
msg.Index = int32(base.Index)
|
|
req.AddData(msg)
|
|
req.AddData(msg)
|
|
|
|
|
|
@@ -659,6 +669,18 @@ func addBondAttrs(bond *Bond, linkInfo *nl.RtAttr) {
|
|
if bond.AdSelect >= 0 {
|
|
if bond.AdSelect >= 0 {
|
|
nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
|
|
nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_SELECT, nl.Uint8Attr(uint8(bond.AdSelect)))
|
|
}
|
|
}
|
|
|
|
+ if bond.AdActorSysPrio >= 0 {
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYS_PRIO, nl.Uint16Attr(uint16(bond.AdActorSysPrio)))
|
|
|
|
+ }
|
|
|
|
+ if bond.AdUserPortKey >= 0 {
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_USER_PORT_KEY, nl.Uint16Attr(uint16(bond.AdUserPortKey)))
|
|
|
|
+ }
|
|
|
|
+ if bond.AdActorSystem != nil {
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_BOND_AD_ACTOR_SYSTEM, []byte(bond.AdActorSystem))
|
|
|
|
+ }
|
|
|
|
+ if bond.TlbDynamicLb >= 0 {
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_BOND_TLB_DYNAMIC_LB, nl.Uint8Attr(uint8(bond.TlbDynamicLb)))
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// LinkAdd adds a new link device. The type and features of the device
|
|
// LinkAdd adds a new link device. The type and features of the device
|
|
@@ -672,7 +694,10 @@ func LinkAdd(link Link) error {
|
|
// are taken fromt the parameters in the link object.
|
|
// are taken fromt the parameters in the link object.
|
|
// Equivalent to: `ip link add $link`
|
|
// Equivalent to: `ip link add $link`
|
|
func (h *Handle) LinkAdd(link Link) error {
|
|
func (h *Handle) LinkAdd(link Link) error {
|
|
- // TODO: set mtu and hardware address
|
|
|
|
|
|
+ return h.linkModify(link, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (h *Handle) linkModify(link Link, flags int) error {
|
|
// TODO: support extra data for macvlan
|
|
// TODO: support extra data for macvlan
|
|
base := link.Attrs()
|
|
base := link.Attrs()
|
|
|
|
|
|
@@ -719,7 +744,7 @@ func (h *Handle) LinkAdd(link Link) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
- req := h.newNetlinkRequest(syscall.RTM_NEWLINK, syscall.NLM_F_CREATE|syscall.NLM_F_EXCL|syscall.NLM_F_ACK)
|
|
|
|
|
|
+ req := h.newNetlinkRequest(syscall.RTM_NEWLINK, flags)
|
|
|
|
|
|
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
msg := nl.NewIfInfomsg(syscall.AF_UNSPEC)
|
|
// TODO: make it shorter
|
|
// TODO: make it shorter
|
|
@@ -767,6 +792,11 @@ func (h *Handle) LinkAdd(link Link) error {
|
|
req.AddData(qlen)
|
|
req.AddData(qlen)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if base.HardwareAddr != nil {
|
|
|
|
+ hwaddr := nl.NewRtAttr(syscall.IFLA_ADDRESS, []byte(base.HardwareAddr))
|
|
|
|
+ req.AddData(hwaddr)
|
|
|
|
+ }
|
|
|
|
+
|
|
if base.Namespace != nil {
|
|
if base.Namespace != nil {
|
|
var attr *nl.RtAttr
|
|
var attr *nl.RtAttr
|
|
switch base.Namespace.(type) {
|
|
switch base.Namespace.(type) {
|
|
@@ -830,6 +860,10 @@ func (h *Handle) LinkAdd(link Link) error {
|
|
addVtiAttrs(vti, linkInfo)
|
|
addVtiAttrs(vti, linkInfo)
|
|
} else if vrf, ok := link.(*Vrf); ok {
|
|
} else if vrf, ok := link.(*Vrf); ok {
|
|
addVrfAttrs(vrf, linkInfo)
|
|
addVrfAttrs(vrf, linkInfo)
|
|
|
|
+ } else if bridge, ok := link.(*Bridge); ok {
|
|
|
|
+ addBridgeAttrs(bridge, linkInfo)
|
|
|
|
+ } else if gtp, ok := link.(*GTP); ok {
|
|
|
|
+ addGTPAttrs(gtp, linkInfo)
|
|
}
|
|
}
|
|
|
|
|
|
req.AddData(linkInfo)
|
|
req.AddData(linkInfo)
|
|
@@ -885,7 +919,7 @@ func (h *Handle) linkByNameDump(name string) (Link, error) {
|
|
return link, nil
|
|
return link, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return nil, fmt.Errorf("Link %s not found", name)
|
|
|
|
|
|
+ return nil, LinkNotFoundError{fmt.Errorf("Link %s not found", name)}
|
|
}
|
|
}
|
|
|
|
|
|
func (h *Handle) linkByAliasDump(alias string) (Link, error) {
|
|
func (h *Handle) linkByAliasDump(alias string) (Link, error) {
|
|
@@ -899,7 +933,7 @@ func (h *Handle) linkByAliasDump(alias string) (Link, error) {
|
|
return link, nil
|
|
return link, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return nil, fmt.Errorf("Link alias %s not found", alias)
|
|
|
|
|
|
+ return nil, LinkNotFoundError{fmt.Errorf("Link alias %s not found", alias)}
|
|
}
|
|
}
|
|
|
|
|
|
// LinkByName finds a link by name and returns a pointer to the object.
|
|
// LinkByName finds a link by name and returns a pointer to the object.
|
|
@@ -985,7 +1019,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
|
|
if err != nil {
|
|
if err != nil {
|
|
if errno, ok := err.(syscall.Errno); ok {
|
|
if errno, ok := err.(syscall.Errno); ok {
|
|
if errno == syscall.ENODEV {
|
|
if errno == syscall.ENODEV {
|
|
- return nil, fmt.Errorf("Link not found")
|
|
|
|
|
|
+ return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil, err
|
|
return nil, err
|
|
@@ -993,7 +1027,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
|
|
|
|
|
|
switch {
|
|
switch {
|
|
case len(msgs) == 0:
|
|
case len(msgs) == 0:
|
|
- return nil, fmt.Errorf("Link not found")
|
|
|
|
|
|
+ return nil, LinkNotFoundError{fmt.Errorf("Link not found")}
|
|
|
|
|
|
case len(msgs) == 1:
|
|
case len(msgs) == 1:
|
|
return LinkDeserialize(nil, msgs[0])
|
|
return LinkDeserialize(nil, msgs[0])
|
|
@@ -1063,6 +1097,8 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
|
|
link = &Vti{}
|
|
link = &Vti{}
|
|
case "vrf":
|
|
case "vrf":
|
|
link = &Vrf{}
|
|
link = &Vrf{}
|
|
|
|
+ case "gtp":
|
|
|
|
+ link = >P{}
|
|
default:
|
|
default:
|
|
link = &GenericLink{LinkType: linkType}
|
|
link = &GenericLink{LinkType: linkType}
|
|
}
|
|
}
|
|
@@ -1092,6 +1128,10 @@ func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
|
|
parseVtiData(link, data)
|
|
parseVtiData(link, data)
|
|
case "vrf":
|
|
case "vrf":
|
|
parseVrfData(link, data)
|
|
parseVrfData(link, data)
|
|
|
|
+ case "bridge":
|
|
|
|
+ parseBridgeData(link, data)
|
|
|
|
+ case "gtp":
|
|
|
|
+ parseGTPData(link, data)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1288,6 +1328,22 @@ func (h *Handle) LinkSetFlood(link Link, mode bool) error {
|
|
return h.setProtinfoAttr(link, mode, nl.IFLA_BRPORT_UNICAST_FLOOD)
|
|
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 {
|
|
func (h *Handle) setProtinfoAttr(link Link, mode bool, attr int) error {
|
|
base := link.Attrs()
|
|
base := link.Attrs()
|
|
h.ensureIndex(base)
|
|
h.ensureIndex(base)
|
|
@@ -1370,7 +1426,7 @@ func parseVxlanData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
}
|
|
}
|
|
|
|
|
|
func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
- bond := NewLinkBond(NewLinkAttrs())
|
|
|
|
|
|
+ bond := link.(*Bond)
|
|
for i := range data {
|
|
for i := range data {
|
|
switch data[i].Attr.Type {
|
|
switch data[i].Attr.Type {
|
|
case nl.IFLA_BOND_MODE:
|
|
case nl.IFLA_BOND_MODE:
|
|
@@ -1419,6 +1475,14 @@ func parseBondData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
bond.AdSelect = BondAdSelect(data[i].Value[0])
|
|
bond.AdSelect = BondAdSelect(data[i].Value[0])
|
|
case nl.IFLA_BOND_AD_INFO:
|
|
case nl.IFLA_BOND_AD_INFO:
|
|
// TODO: implement
|
|
// 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])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1566,6 +1630,8 @@ func addXdpAttrs(xdp *LinkXdp, req *nl.NetlinkRequest) {
|
|
b := make([]byte, 4)
|
|
b := make([]byte, 4)
|
|
native.PutUint32(b, uint32(xdp.Fd))
|
|
native.PutUint32(b, uint32(xdp.Fd))
|
|
nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
|
|
nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FD, b)
|
|
|
|
+ native.PutUint32(b, xdp.Flags)
|
|
|
|
+ nl.NewRtAttrChild(attrs, nl.IFLA_XDP_FLAGS, b)
|
|
req.AddData(attrs)
|
|
req.AddData(attrs)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1581,6 +1647,8 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
|
|
xdp.Fd = int(native.Uint32(attr.Value[0:4]))
|
|
xdp.Fd = int(native.Uint32(attr.Value[0:4]))
|
|
case nl.IFLA_XDP_ATTACHED:
|
|
case nl.IFLA_XDP_ATTACHED:
|
|
xdp.Attached = attr.Value[0] != 0
|
|
xdp.Attached = attr.Value[0] != 0
|
|
|
|
+ case nl.IFLA_XDP_FLAGS:
|
|
|
|
+ xdp.Flags = native.Uint32(attr.Value[0:4])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return xdp, nil
|
|
return xdp, nil
|
|
@@ -1678,3 +1746,53 @@ func parseVrfData(link Link, data []syscall.NetlinkRouteAttr) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func addBridgeAttrs(bridge *Bridge, linkInfo *nl.RtAttr) {
|
|
|
|
+ data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
|
+ if bridge.MulticastSnooping != nil {
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_BR_MCAST_SNOOPING, boolToByte(*bridge.MulticastSnooping))
|
|
|
|
+ }
|
|
|
|
+ if bridge.HelloTime != nil {
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_BR_HELLO_TIME, nl.Uint32Attr(*bridge.HelloTime))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func parseBridgeData(bridge Link, data []syscall.NetlinkRouteAttr) {
|
|
|
|
+ br := bridge.(*Bridge)
|
|
|
|
+ for _, datum := range data {
|
|
|
|
+ switch datum.Attr.Type {
|
|
|
|
+ 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
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func addGTPAttrs(gtp *GTP, linkInfo *nl.RtAttr) {
|
|
|
|
+ data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GTP_FD0, nl.Uint32Attr(uint32(gtp.FD0)))
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GTP_FD1, nl.Uint32Attr(uint32(gtp.FD1)))
|
|
|
|
+ nl.NewRtAttrChild(data, nl.IFLA_GTP_PDP_HASHSIZE, nl.Uint32Attr(131072))
|
|
|
|
+ if gtp.Role != nl.GTP_ROLE_GGSN {
|
|
|
|
+ nl.NewRtAttrChild(data, 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))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|