mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-18 12:59:31 +00:00
173 lines
3.9 KiB
Go
173 lines
3.9 KiB
Go
package odp
|
|
|
|
import (
|
|
"fmt"
|
|
"syscall"
|
|
)
|
|
|
|
// Datapaths are identified by the ifindex of their netdev.
|
|
type DatapathID int32
|
|
|
|
type datapathInfo struct {
|
|
ifindex DatapathID
|
|
name string
|
|
}
|
|
|
|
func (dpif *Dpif) parseDatapathInfo(msg *NlMsgParser) (res datapathInfo, err error) {
|
|
_, ovshdr, err := dpif.checkNlMsgHeaders(msg, DATAPATH, OVS_DP_CMD_NEW)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
res.ifindex = ovshdr.datapathID()
|
|
attrs, err := msg.TakeAttrs()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
res.name, err = attrs.GetString(OVS_DP_ATTR_NAME)
|
|
return
|
|
}
|
|
|
|
type DatapathHandle struct {
|
|
dpif *Dpif
|
|
ifindex DatapathID
|
|
}
|
|
|
|
func (dp DatapathHandle) ID() DatapathID {
|
|
return dp.ifindex
|
|
}
|
|
|
|
func (dp DatapathHandle) Reopen() (DatapathHandle, error) {
|
|
dpif, err := dp.dpif.Reopen()
|
|
return DatapathHandle{dpif: dpif, ifindex: dp.ifindex}, err
|
|
}
|
|
|
|
func (dpif *Dpif) CreateDatapath(name string) (DatapathHandle, error) {
|
|
var features uint32 = OVS_DP_F_UNALIGNED | OVS_DP_F_VPORT_PIDS
|
|
|
|
req := NewNlMsgBuilder(RequestFlags, dpif.families[DATAPATH].id)
|
|
req.PutGenlMsghdr(OVS_DP_CMD_NEW, OVS_DATAPATH_VERSION)
|
|
req.putOvsHeader(0)
|
|
req.PutStringAttr(OVS_DP_ATTR_NAME, name)
|
|
req.PutUint32Attr(OVS_DP_ATTR_UPCALL_PID, 0)
|
|
req.PutUint32Attr(OVS_DP_ATTR_USER_FEATURES, features)
|
|
|
|
resp, err := dpif.sock.Request(req)
|
|
if err != nil {
|
|
return DatapathHandle{}, err
|
|
}
|
|
|
|
dpi, err := dpif.parseDatapathInfo(resp)
|
|
if err != nil {
|
|
return DatapathHandle{}, err
|
|
}
|
|
|
|
return DatapathHandle{dpif: dpif, ifindex: dpi.ifindex}, nil
|
|
}
|
|
|
|
func IsDatapathNameAlreadyExistsError(err error) bool {
|
|
return err == NetlinkError(syscall.EEXIST)
|
|
}
|
|
|
|
func (dpif *Dpif) LookupDatapath(name string) (DatapathHandle, error) {
|
|
req := NewNlMsgBuilder(RequestFlags, dpif.families[DATAPATH].id)
|
|
req.PutGenlMsghdr(OVS_DP_CMD_GET, OVS_DATAPATH_VERSION)
|
|
req.putOvsHeader(0)
|
|
req.PutStringAttr(OVS_DP_ATTR_NAME, name)
|
|
|
|
resp, err := dpif.sock.Request(req)
|
|
if err != nil {
|
|
return DatapathHandle{}, err
|
|
}
|
|
|
|
dpi, err := dpif.parseDatapathInfo(resp)
|
|
if err != nil {
|
|
return DatapathHandle{}, err
|
|
}
|
|
|
|
return DatapathHandle{dpif: dpif, ifindex: dpi.ifindex}, nil
|
|
}
|
|
|
|
type Datapath struct {
|
|
Handle DatapathHandle
|
|
Name string
|
|
}
|
|
|
|
func (dpif *Dpif) LookupDatapathByID(ifindex DatapathID) (Datapath, error) {
|
|
req := NewNlMsgBuilder(RequestFlags, dpif.families[DATAPATH].id)
|
|
req.PutGenlMsghdr(OVS_DP_CMD_GET, OVS_DATAPATH_VERSION)
|
|
req.putOvsHeader(ifindex)
|
|
|
|
resp, err := dpif.sock.Request(req)
|
|
if err != nil {
|
|
return Datapath{}, err
|
|
}
|
|
|
|
dpi, err := dpif.parseDatapathInfo(resp)
|
|
if err != nil {
|
|
return Datapath{}, err
|
|
}
|
|
|
|
return Datapath{
|
|
Handle: DatapathHandle{dpif: dpif, ifindex: ifindex},
|
|
Name: dpi.name,
|
|
}, nil
|
|
}
|
|
|
|
func IsNoSuchDatapathError(err error) bool {
|
|
return err == NetlinkError(syscall.ENODEV)
|
|
}
|
|
|
|
func (dpif *Dpif) EnumerateDatapaths() (map[string]DatapathHandle, error) {
|
|
res := make(map[string]DatapathHandle)
|
|
|
|
req := NewNlMsgBuilder(DumpFlags, dpif.families[DATAPATH].id)
|
|
req.PutGenlMsghdr(OVS_DP_CMD_GET, OVS_DATAPATH_VERSION)
|
|
req.putOvsHeader(0)
|
|
|
|
consumer := func(resp *NlMsgParser) error {
|
|
dpi, err := dpif.parseDatapathInfo(resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res[dpi.name] = DatapathHandle{dpif: dpif, ifindex: dpi.ifindex}
|
|
return nil
|
|
}
|
|
|
|
err := dpif.sock.RequestMulti(req, consumer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func (dp DatapathHandle) Delete() error {
|
|
req := NewNlMsgBuilder(RequestFlags, dp.dpif.families[DATAPATH].id)
|
|
req.PutGenlMsghdr(OVS_DP_CMD_DEL, OVS_DATAPATH_VERSION)
|
|
req.putOvsHeader(dp.ifindex)
|
|
|
|
_, err := dp.dpif.sock.Request(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
dp.dpif = nil
|
|
dp.ifindex = 0
|
|
return nil
|
|
}
|
|
|
|
func (dp DatapathHandle) checkNlMsgHeaders(msg *NlMsgParser, family int, cmd int) error {
|
|
_, ovshdr, err := dp.dpif.checkNlMsgHeaders(msg, family, cmd)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if ovshdr.datapathID() != dp.ifindex {
|
|
return fmt.Errorf("wrong datapath ifindex received (got %d, expected %d)", ovshdr.datapathID(), dp.ifindex)
|
|
}
|
|
|
|
return nil
|
|
}
|