Fixed rtnetlink attributes packaging into netlink message.

I've also added NetworkLinkDel() function which allows deleting
of the existing network links.

Docker-DCO-1.1-Signed-off-by: Milos Gajdos <milosgajdos83@gmail.com> (github: milosgajdos83)
This commit is contained in:
Milos Gajdos 2014-08-04 18:29:06 +01:00
parent f538117a7b
commit c5f4d90da5
3 changed files with 77 additions and 15 deletions

View File

@ -189,13 +189,15 @@ func newRtAttrChild(parent *RtAttr, attrType int, data []byte) *RtAttr {
}
func (a *RtAttr) Len() int {
if len(a.children) == 0 {
return (syscall.SizeofRtAttr + len(a.Data))
}
l := 0
for _, child := range a.children {
l += child.Len() + syscall.SizeofRtAttr
}
if l == 0 {
l++
l += child.Len()
}
l += syscall.SizeofRtAttr
return rtaAlignOf(l + len(a.Data))
}
@ -203,7 +205,7 @@ func (a *RtAttr) ToWireFormat() []byte {
native := nativeEndian()
length := a.Len()
buf := make([]byte, rtaAlignOf(length+syscall.SizeofRtAttr))
buf := make([]byte, rtaAlignOf(length))
if a.Data != nil {
copy(buf[4:], a.Data)
@ -216,11 +218,10 @@ func (a *RtAttr) ToWireFormat() []byte {
}
}
if l := uint16(rtaAlignOf(length)); l != 0 {
native.PutUint16(buf[0:2], l+1)
if l := uint16(length); l != 0 {
native.PutUint16(buf[0:2], l)
}
native.PutUint16(buf[2:4], a.Type)
return buf
}
@ -700,6 +701,10 @@ func nonZeroTerminated(s string) []byte {
// Add a new network link of a specified type. This is identical to
// running: ip add link $name type $linkType
func NetworkLinkAdd(name string, linkType string) error {
if name == "" || linkType == "" {
return fmt.Errorf("Neither link name nor link type can be empty!")
}
s, err := getNetlinkSocket()
if err != nil {
return err
@ -711,15 +716,43 @@ func NetworkLinkAdd(name string, linkType string) error {
msg := newIfInfomsg(syscall.AF_UNSPEC)
wb.AddData(msg)
if name != "" {
nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
wb.AddData(nameData)
linkInfo := newRtAttr(syscall.IFLA_LINKINFO, nil)
newRtAttrChild(linkInfo, IFLA_INFO_KIND, nonZeroTerminated(linkType))
wb.AddData(linkInfo)
nameData := newRtAttr(syscall.IFLA_IFNAME, zeroTerminated(name))
wb.AddData(nameData)
if err := s.Send(wb); err != nil {
return err
}
kindData := newRtAttr(IFLA_INFO_KIND, nonZeroTerminated(linkType))
return s.HandleAck(wb.Seq)
}
infoData := newRtAttr(syscall.IFLA_LINKINFO, kindData.ToWireFormat())
wb.AddData(infoData)
// Delete a network link. This is identical to
// running: ip link del $name
func NetworkLinkDel(name string) error {
if name == "" {
return fmt.Errorf("Network link name can not be empty!")
}
s, err := getNetlinkSocket()
if err != nil {
return err
}
defer s.Close()
iface, err := net.InterfaceByName(name)
if err != nil {
return err
}
wb := newNetlinkRequest(syscall.RTM_DELLINK, syscall.NLM_F_ACK)
msg := newIfInfomsg(syscall.AF_UNSPEC)
msg.Index = int32(iface.Index)
wb.AddData(msg)
if err := s.Send(wb); err != nil {
return err

View File

@ -27,10 +27,35 @@ func TestCreateBridgeWithMac(t *testing.T) {
}
if _, err := net.InterfaceByName(name); err == nil {
t.Fatal("expected error getting interface because bridge was deleted")
t.Fatal("expected error getting interface because %s bridge was deleted", name)
}
}
func TestCreateBridgeLink(t *testing.T) {
if testing.Short() {
return
}
name := "mybrlink"
if err := NetworkLinkAdd(name, "bridge"); err != nil {
log.Fatal(err)
}
if _, err := net.InterfaceByName(name); err != nil {
t.Fatal(err)
}
if err := NetworkLinkDel(name); err != nil {
t.Fatal(err)
}
if _, err := net.InterfaceByName(name); err == nil {
t.Fatal("expected error getting interface because %s bridge was deleted", name)
}
}
func TestCreateVethPair(t *testing.T) {
if testing.Short() {
return

View File

@ -19,6 +19,10 @@ func NetworkLinkAdd(name string, linkType string) error {
return ErrNotImplemented
}
func NetworkLinkDel(name string) error {
return ErrNotImplemented
}
func NetworkLinkUp(iface *net.Interface) error {
return ErrNotImplemented
}