Files
weave-scope/vendor/github.com/weaveworks/go-odp/odp/genetlink.go
2015-12-04 09:57:44 +00:00

102 lines
2.3 KiB
Go

package odp
import (
"fmt"
"syscall"
)
type GenlFamily struct {
id uint16
mcGroups map[string]uint32
}
func (nlmsg *NlMsgBuilder) PutGenlMsghdr(cmd uint8, version uint8) *GenlMsghdr {
pos := nlmsg.AlignGrow(syscall.NLMSG_ALIGNTO, SizeofGenlMsghdr)
res := genlMsghdrAt(nlmsg.buf, pos)
res.Cmd = cmd
res.Version = version
return res
}
func (nlmsg *NlMsgParser) CheckGenlMsghdr(cmd int) (*GenlMsghdr, error) {
pos, err := nlmsg.AlignAdvance(syscall.NLMSG_ALIGNTO, SizeofGenlMsghdr)
if err != nil {
return nil, err
}
gh := genlMsghdrAt(nlmsg.data, pos)
if cmd >= 0 && gh.Cmd != uint8(cmd) {
return nil, fmt.Errorf("generic netlink response has wrong cmd (got %d, expected %d)", gh.Cmd, cmd)
}
// Deliberately ignore the version field in the genl header.
// It's unclear exactly what its meaning is, and how we should
// handle it. E.g., if the version is higher than we expect,
// should we still try to handle the message? It's unclear,
// but the fact that ODP bumped the kernel
// OVS_DATAPATH_VERSION from 1 to 2 while expecting existing
// userspace to keep working suggests that we should be
// libreral in what we accept.
return gh, nil
}
func (s *NetlinkSocket) LookupGenlFamily(name string) (family GenlFamily, err error) {
req := NewNlMsgBuilder(RequestFlags, GENL_ID_CTRL)
req.PutGenlMsghdr(CTRL_CMD_GETFAMILY, 0)
req.PutStringAttr(CTRL_ATTR_FAMILY_NAME, name)
resp, err := s.Request(req)
if err != nil {
return
}
_, err = resp.ExpectNlMsghdr(GENL_ID_CTRL)
if err != nil {
return
}
_, err = resp.CheckGenlMsghdr(CTRL_CMD_NEWFAMILY)
if err != nil {
return
}
attrs, err := resp.TakeAttrs()
if err != nil {
return
}
family.id, err = attrs.GetUint16(CTRL_ATTR_FAMILY_ID)
if err != nil {
return
}
mcGroupAttrs, err := attrs.GetNestedAttrs(CTRL_ATTR_MCAST_GROUPS, true)
if err != nil || mcGroupAttrs == nil {
return
}
family.mcGroups = make(map[string]uint32)
for _, data := range mcGroupAttrs {
groupAttrs, err := ParseNestedAttrs(data)
if err != nil {
return family, err
}
id, err := groupAttrs.GetUint32(CTRL_ATTR_MCAST_GRP_ID)
if err != nil {
return family, err
}
name, err := groupAttrs.GetString(CTRL_ATTR_MCAST_GRP_NAME)
if err != nil {
return family, err
}
family.mcGroups[name] = id
}
return
}