Add support for VTI and IPIP

This commit is contained in:
JC Martin 2016-10-29 22:46:24 -07:00 committed by Vish Ishaya
parent 18675e4393
commit 9438c6ff27
7 changed files with 229 additions and 9 deletions

View File

@ -13,6 +13,7 @@ type Addr struct {
Label string
Flags int
Scope int
Peer *net.IPNet
}
// String returns $ip/$netmask $label
@ -43,3 +44,10 @@ func (a Addr) Equal(x Addr) bool {
// ignore label for comparison
return a.IP.Equal(x.IP) && sizea == sizeb
}
func (a Addr) PeerEqual(x Addr) bool {
sizea, _ := a.Peer.Mask.Size()
sizeb, _ := x.Peer.Mask.Size()
// ignore label for comparison
return a.Peer.IP.Equal(x.Peer.IP) && sizea == sizeb
}

View File

@ -56,17 +56,27 @@ func (h *Handle) addrHandle(link Link, addr *Addr, req *nl.NetlinkRequest) error
msg.Prefixlen = uint8(prefixlen)
req.AddData(msg)
var addrData []byte
var localAddrData []byte
if family == FAMILY_V4 {
addrData = addr.IP.To4()
localAddrData = addr.IP.To4()
} else {
addrData = addr.IP.To16()
localAddrData = addr.IP.To16()
}
localData := nl.NewRtAttr(syscall.IFA_LOCAL, addrData)
localData := nl.NewRtAttr(syscall.IFA_LOCAL, localAddrData)
req.AddData(localData)
var peerAddrData []byte
if addr.Peer != nil {
if family == FAMILY_V4 {
peerAddrData = addr.Peer.IP.To4()
} else {
peerAddrData = addr.Peer.IP.To16()
}
} else {
peerAddrData = localAddrData
}
addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, addrData)
addressData := nl.NewRtAttr(syscall.IFA_ADDRESS, peerAddrData)
req.AddData(addressData)
if addr.Flags != 0 {
@ -161,11 +171,13 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) {
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
}
addr.Peer = dst
case syscall.IFA_LOCAL:
local = &net.IPNet{
IP: attr.Value,
Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)),
}
addr.IPNet = local
case syscall.IFA_LABEL:
addr.Label = string(attr.Value[:len(attr.Value)-1])
case IFA_FLAGS:

View File

@ -13,6 +13,7 @@ func TestAddr(t *testing.T) {
}
// TODO: IFA_F_PERMANENT does not seem to be set by default on older kernels?
var address = &net.IPNet{IP: net.IPv4(127, 0, 0, 2), Mask: net.CIDRMask(24, 32)}
var peer = &net.IPNet{IP: net.IPv4(127, 0, 0, 3), Mask: net.CIDRMask(24, 32)}
var addrTests = []struct {
addr *Addr
expected *Addr
@ -37,6 +38,10 @@ func TestAddr(t *testing.T) {
&Addr{IPNet: address, Scope: syscall.RT_SCOPE_NOWHERE},
&Addr{IPNet: address, Label: "lo", Flags: syscall.IFA_F_PERMANENT, Scope: syscall.RT_SCOPE_NOWHERE},
},
{
&Addr{IPNet: address, Peer: peer},
&Addr{IPNet: address, Peer: peer, Label: "lo", Scope: syscall.RT_SCOPE_UNIVERSE, Flags: syscall.IFA_F_PERMANENT},
},
}
tearDown := setUpNetlinkTest(t)
@ -77,6 +82,12 @@ func TestAddr(t *testing.T) {
t.Fatalf("Address scope not set properly, got=%d, expected=%d", addrs[0].Scope, tt.expected.Scope)
}
if tt.expected.Peer != nil {
if !addrs[0].PeerEqual(*tt.expected) {
t.Fatalf("Peer Address ip no set properly, got=%s, expected=%s", addrs[0].Peer, tt.expected.Peer)
}
}
// Pass FAMILY_V4, we should get the same results as FAMILY_ALL
addrs, err = AddrList(link, FAMILY_V4)
if err != nil {

35
link.go
View File

@ -589,6 +589,41 @@ func (gretap *Gretap) Type() string {
return "gretap"
}
type Iptun struct {
LinkAttrs
Ttl uint8
Tos uint8
PMtuDisc uint8
Link uint32
Local net.IP
Remote net.IP
}
func (iptun *Iptun) Attrs() *LinkAttrs {
return &iptun.LinkAttrs
}
func (iptun *Iptun) Type() string {
return "ipip"
}
type Vti struct {
LinkAttrs
IKey uint32
OKey uint32
Link uint32
Local net.IP
Remote net.IP
}
func (vti *Vti) Attrs() *LinkAttrs {
return &vti.LinkAttrs
}
func (iptun *Vti) Type() string {
return "vti"
}
// iproute2 supported devices;
// vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
// bridge | bond | ipoib | ip6tnl | ipip | sit | vxlan |

View File

@ -783,6 +783,10 @@ func (h *Handle) LinkAdd(link Link) error {
}
} else if gretap, ok := link.(*Gretap); ok {
addGretapAttrs(gretap, linkInfo)
} else if iptun, ok := link.(*Iptun); ok {
addIptunAttrs(iptun, linkInfo)
} else if vti, ok := link.(*Vti); ok {
addVtiAttrs(vti, linkInfo)
}
req.AddData(linkInfo)
@ -1006,6 +1010,10 @@ func LinkDeserialize(m []byte) (Link, error) {
link = &Macvtap{}
case "gretap":
link = &Gretap{}
case "ipip":
link = &Iptun{}
case "vti":
link = &Vti{}
default:
link = &GenericLink{LinkType: linkType}
}
@ -1029,6 +1037,10 @@ func LinkDeserialize(m []byte) (Link, error) {
parseMacvtapData(link, data)
case "gretap":
parseGretapData(link, data)
case "ipip":
parseIptunData(link, data)
case "vti":
parseVtiData(link, data)
}
}
}
@ -1518,3 +1530,79 @@ func parseLinkXdp(data []byte) (*LinkXdp, error) {
}
return xdp, nil
}
func addIptunAttrs(iptun *Iptun, linkInfo *nl.RtAttr) {
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
ip := iptun.Local.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LOCAL, []byte(ip))
}
ip = iptun.Remote.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_REMOTE, []byte(ip))
}
if iptun.Link != 0 {
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_LINK, nl.Uint32Attr(iptun.Link))
}
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_PMTUDISC, nl.Uint8Attr(iptun.PMtuDisc))
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TTL, nl.Uint8Attr(iptun.Ttl))
nl.NewRtAttrChild(data, nl.IFLA_IPTUN_TOS, nl.Uint8Attr(iptun.Tos))
}
func parseIptunData(link Link, data []syscall.NetlinkRouteAttr) {
iptun := link.(*Iptun)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_IPTUN_LOCAL:
iptun.Local = net.IP(datum.Value[0:4])
case nl.IFLA_IPTUN_REMOTE:
iptun.Remote = net.IP(datum.Value[0:4])
case nl.IFLA_IPTUN_TTL:
iptun.Ttl = uint8(datum.Value[0])
case nl.IFLA_IPTUN_TOS:
iptun.Tos = uint8(datum.Value[0])
case nl.IFLA_IPTUN_PMTUDISC:
iptun.PMtuDisc = uint8(datum.Value[0])
}
}
}
func addVtiAttrs(vti *Vti, linkInfo *nl.RtAttr) {
data := nl.NewRtAttrChild(linkInfo, nl.IFLA_INFO_DATA, nil)
ip := vti.Local.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_VTI_LOCAL, []byte(ip))
}
ip = vti.Remote.To4()
if ip != nil {
nl.NewRtAttrChild(data, nl.IFLA_VTI_REMOTE, []byte(ip))
}
if vti.Link != 0 {
nl.NewRtAttrChild(data, nl.IFLA_VTI_LINK, nl.Uint32Attr(vti.Link))
}
nl.NewRtAttrChild(data, nl.IFLA_VTI_IKEY, htonl(vti.IKey))
nl.NewRtAttrChild(data, nl.IFLA_VTI_OKEY, htonl(vti.OKey))
}
func parseVtiData(link Link, data []syscall.NetlinkRouteAttr) {
vti := link.(*Vti)
for _, datum := range data {
switch datum.Attr.Type {
case nl.IFLA_VTI_LOCAL:
vti.Local = net.IP(datum.Value[0:4])
case nl.IFLA_VTI_REMOTE:
vti.Remote = net.IP(datum.Value[0:4])
case nl.IFLA_VTI_IKEY:
vti.IKey = ntohl(datum.Value[0:4])
case nl.IFLA_VTI_OKEY:
vti.OKey = ntohl(datum.Value[0:4])
}
}
}

View File

@ -21,7 +21,6 @@ func testLinkAddDel(t *testing.T, link Link) {
if err != nil {
t.Fatal(err)
}
num := len(links)
if err := LinkAdd(link); err != nil {
t.Fatal(err)
@ -120,6 +119,20 @@ func testLinkAddDel(t *testing.T, link Link) {
}
}
if _, ok := link.(*Vti); ok {
_, ok := result.(*Vti)
if !ok {
t.Fatal("Result of create is not a vti")
}
}
if _, ok := link.(*Iptun); ok {
_, ok := result.(*Iptun)
if !ok {
t.Fatal("Result of create is not a iptun")
}
}
if err = LinkDel(link); err != nil {
t.Fatal(err)
}
@ -129,9 +142,10 @@ func testLinkAddDel(t *testing.T, link Link) {
t.Fatal(err)
}
if len(links) != num {
t.Fatal("Link not removed properly")
return
for _, l := range links {
if l.Attrs().Name == link.Attrs().Name {
t.Fatal("Link not removed properly")
}
}
}
@ -969,3 +983,26 @@ func TestLinkXdp(t *testing.T) {
t.Fatal(err)
}
}
func TestLinkAddDelIptun(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
testLinkAddDel(t, &Iptun{
LinkAttrs: LinkAttrs{Name: "iptunfoo"},
PMtuDisc: 1,
Local: net.IPv4(127, 0, 0, 1),
Remote: net.IPv4(127, 0, 0, 1)})
}
func TestLinkAddDelVti(t *testing.T) {
tearDown := setUpNetlinkTest(t)
defer tearDown()
testLinkAddDel(t, &Vti{
LinkAttrs: LinkAttrs{Name: "vtifoo"},
IKey: 0x101,
OKey: 0x101,
Local: net.IPv4(127, 0, 0, 1),
Remote: net.IPv4(127, 0, 0, 1)})
}

View File

@ -418,3 +418,32 @@ const (
IFLA_XDP_ATTACHED /* read-only bool indicating if prog is attached */
IFLA_XDP_MAX = IFLA_XDP_ATTACHED
)
const (
IFLA_IPTUN_UNSPEC = iota
IFLA_IPTUN_LINK
IFLA_IPTUN_LOCAL
IFLA_IPTUN_REMOTE
IFLA_IPTUN_TTL
IFLA_IPTUN_TOS
IFLA_IPTUN_ENCAP_LIMIT
IFLA_IPTUN_FLOWINFO
IFLA_IPTUN_FLAGS
IFLA_IPTUN_PROTO
IFLA_IPTUN_PMTUDISC
IFLA_IPTUN_6RD_PREFIX
IFLA_IPTUN_6RD_RELAY_PREFIX
IFLA_IPTUN_6RD_PREFIXLEN
IFLA_IPTUN_6RD_RELAY_PREFIXLEN
IFLA_IPTUN_MAX = IFLA_IPTUN_6RD_RELAY_PREFIXLEN
)
const (
IFLA_VTI_UNSPEC = iota
IFLA_VTI_LINK
IFLA_VTI_IKEY
IFLA_VTI_OKEY
IFLA_VTI_LOCAL
IFLA_VTI_REMOTE
IFLA_VTI_MAX = IFLA_VTI_REMOTE
)