mirror of https://github.com/vishvananda/netlink
Add support for VTI and IPIP
This commit is contained in:
parent
18675e4393
commit
9438c6ff27
8
addr.go
8
addr.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
11
addr_test.go
11
addr_test.go
|
@ -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
35
link.go
|
@ -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 |
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
43
link_test.go
43
link_test.go
|
@ -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 {
|
||||
for _, l := range links {
|
||||
if l.Attrs().Name == link.Attrs().Name {
|
||||
t.Fatal("Link not removed properly")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue