mirror of
https://github.com/vishvananda/netlink
synced 2024-12-29 02:02:21 +00:00
Parse IFLA_PROTINFO in LinkDeserialize
Extract and parse IFLA_PROTINFO fields from RTM_NEWLINK AF_BRIDGE netlink messages.
This commit is contained in:
parent
a4f22d8ad2
commit
266f02d3a8
1
link.go
1
link.go
@ -35,6 +35,7 @@ type LinkAttrs struct {
|
||||
Promisc int
|
||||
Xdp *LinkXdp
|
||||
EncapType string
|
||||
Protinfo *Protinfo
|
||||
}
|
||||
|
||||
// NewLinkAttrs returns LinkAttrs structure filled with default values
|
||||
|
@ -953,7 +953,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
|
||||
return nil, fmt.Errorf("Link not found")
|
||||
|
||||
case len(msgs) == 1:
|
||||
return LinkDeserialize(msgs[0])
|
||||
return LinkDeserialize(nil, msgs[0])
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("More than one link found")
|
||||
@ -962,7 +962,7 @@ func execGetLink(req *nl.NetlinkRequest) (Link, error) {
|
||||
|
||||
// linkDeserialize deserializes a raw message received from netlink into
|
||||
// a link object.
|
||||
func LinkDeserialize(m []byte) (Link, error) {
|
||||
func LinkDeserialize(hdr *syscall.NlMsghdr, m []byte) (Link, error) {
|
||||
msg := nl.DeserializeIfInfomsg(m)
|
||||
|
||||
attrs, err := nl.ParseRouteAttr(m[msg.Len():])
|
||||
@ -1074,6 +1074,15 @@ func LinkDeserialize(m []byte) (Link, error) {
|
||||
return nil, err
|
||||
}
|
||||
base.Xdp = xdp
|
||||
case syscall.IFLA_PROTINFO | syscall.NLA_F_NESTED:
|
||||
if hdr != nil && hdr.Type == syscall.RTM_NEWLINK &&
|
||||
msg.Family == syscall.AF_BRIDGE {
|
||||
attrs, err := nl.ParseRouteAttr(attr.Value[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
base.Protinfo = parseProtinfo(attrs)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Links that don't have IFLA_INFO_KIND are hardware devices
|
||||
@ -1108,7 +1117,7 @@ func (h *Handle) LinkList() ([]Link, error) {
|
||||
|
||||
var res []Link
|
||||
for _, m := range msgs {
|
||||
link, err := LinkDeserialize(m)
|
||||
link, err := LinkDeserialize(nil, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1157,7 +1166,7 @@ func linkSubscribe(newNs, curNs netns.NsHandle, ch chan<- LinkUpdate, done <-cha
|
||||
}
|
||||
for _, m := range msgs {
|
||||
ifmsg := nl.DeserializeIfInfomsg(m.Data)
|
||||
link, err := LinkDeserialize(m.Data)
|
||||
link, err := LinkDeserialize(&m.Header, m.Data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
52
link_test.go
52
link_test.go
@ -1006,3 +1006,55 @@ func TestLinkAddDelVti(t *testing.T) {
|
||||
Local: net.IPv4(127, 0, 0, 1),
|
||||
Remote: net.IPv4(127, 0, 0, 1)})
|
||||
}
|
||||
|
||||
func TestLinkSubscribeWithProtinfo(t *testing.T) {
|
||||
tearDown := setUpNetlinkTest(t)
|
||||
defer tearDown()
|
||||
|
||||
master := &Bridge{LinkAttrs{Name: "foo"}}
|
||||
if err := LinkAdd(master); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
slave := &Veth{
|
||||
LinkAttrs: LinkAttrs{
|
||||
Name: "bar",
|
||||
TxQLen: testTxQLen,
|
||||
MTU: 1400,
|
||||
MasterIndex: master.Attrs().Index,
|
||||
},
|
||||
PeerName: "bar-peer",
|
||||
}
|
||||
if err := LinkAdd(slave); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ch := make(chan LinkUpdate)
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
if err := LinkSubscribe(ch, done); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := LinkSetHairpin(slave, true); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
select {
|
||||
case update := <-ch:
|
||||
if !(update.Attrs().Name == "bar" && update.Attrs().Protinfo != nil &&
|
||||
update.Attrs().Protinfo.Hairpin) {
|
||||
t.Fatal("Hairpin update not received as expected")
|
||||
}
|
||||
case <-time.After(time.Minute):
|
||||
t.Fatal("Hairpin update timed out")
|
||||
}
|
||||
|
||||
if err := LinkDel(slave); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := LinkDel(master); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -40,25 +40,31 @@ func (h *Handle) LinkGetProtinfo(link Link) (Protinfo, error) {
|
||||
if err != nil {
|
||||
return pi, err
|
||||
}
|
||||
var pi Protinfo
|
||||
for _, info := range infos {
|
||||
switch info.Attr.Type {
|
||||
case nl.IFLA_BRPORT_MODE:
|
||||
pi.Hairpin = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_GUARD:
|
||||
pi.Guard = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_FAST_LEAVE:
|
||||
pi.FastLeave = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_PROTECT:
|
||||
pi.RootBlock = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_LEARNING:
|
||||
pi.Learning = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_UNICAST_FLOOD:
|
||||
pi.Flood = byteToBool(info.Value[0])
|
||||
}
|
||||
}
|
||||
pi = *parseProtinfo(infos)
|
||||
|
||||
return pi, nil
|
||||
}
|
||||
}
|
||||
return pi, fmt.Errorf("Device with index %d not found", base.Index)
|
||||
}
|
||||
|
||||
func parseProtinfo(infos []syscall.NetlinkRouteAttr) *Protinfo {
|
||||
var pi Protinfo
|
||||
for _, info := range infos {
|
||||
switch info.Attr.Type {
|
||||
case nl.IFLA_BRPORT_MODE:
|
||||
pi.Hairpin = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_GUARD:
|
||||
pi.Guard = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_FAST_LEAVE:
|
||||
pi.FastLeave = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_PROTECT:
|
||||
pi.RootBlock = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_LEARNING:
|
||||
pi.Learning = byteToBool(info.Value[0])
|
||||
case nl.IFLA_BRPORT_UNICAST_FLOOD:
|
||||
pi.Flood = byteToBool(info.Value[0])
|
||||
}
|
||||
}
|
||||
return &pi
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user