summaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/zclient.go136
-rw-r--r--server/zclient_test.go18
2 files changed, 61 insertions, 93 deletions
diff --git a/server/zclient.go b/server/zclient.go
index 89747fe3..0b541353 100644
--- a/server/zclient.go
+++ b/server/zclient.go
@@ -199,24 +199,18 @@ func filterOutExternalPath(paths pathList) pathList {
return filteredPaths
}
-func newIPRouteMessage(dst pathList, version uint8, vrfId uint16) *zebra.Message {
+func newIPRouteBody(dst pathList) (*zebra.IPRouteBody, bool) {
paths := filterOutExternalPath(dst)
if len(paths) == 0 {
- return nil
+ return nil, false
}
path := paths[0]
l := strings.SplitN(path.GetNlri().String(), "/", 2)
- var command zebra.API_TYPE
var prefix net.IP
nexthops := make([]net.IP, 0, len(paths))
switch path.GetRouteFamily() {
case bgp.RF_IPv4_UC, bgp.RF_IPv4_VPN:
- if path.IsWithdraw == true {
- command = zebra.IPV4_ROUTE_DELETE
- } else {
- command = zebra.IPV4_ROUTE_ADD
- }
if path.GetRouteFamily() == bgp.RF_IPv4_UC {
prefix = path.GetNlri().(*bgp.IPAddrPrefix).IPAddrPrefixDefault.Prefix.To4()
} else {
@@ -226,11 +220,6 @@ func newIPRouteMessage(dst pathList, version uint8, vrfId uint16) *zebra.Message
nexthops = append(nexthops, p.GetNexthop().To4())
}
case bgp.RF_IPv6_UC, bgp.RF_IPv6_VPN:
- if path.IsWithdraw == true {
- command = zebra.IPV6_ROUTE_DELETE
- } else {
- command = zebra.IPV6_ROUTE_ADD
- }
if path.GetRouteFamily() == bgp.RF_IPv6_UC {
prefix = path.GetNlri().(*bgp.IPv6AddrPrefix).IPAddrPrefixDefault.Prefix.To16()
} else {
@@ -240,7 +229,7 @@ func newIPRouteMessage(dst pathList, version uint8, vrfId uint16) *zebra.Message
nexthops = append(nexthops, p.GetNexthop().To16())
}
default:
- return nil
+ return nil, false
}
msgFlags := zebra.MESSAGE_NEXTHOP
plen, _ := strconv.Atoi(l[1])
@@ -255,50 +244,38 @@ func newIPRouteMessage(dst pathList, version uint8, vrfId uint16) *zebra.Message
} else if info.MultihopTtl > 0 {
flags = zebra.FLAG_INTERNAL
}
- return &zebra.Message{
- Header: zebra.Header{
- Len: zebra.HeaderSize(version),
- Marker: zebra.HEADER_MARKER,
- Version: version,
- Command: command,
- VrfId: vrfId,
- },
- Body: &zebra.IPRouteBody{
- Type: zebra.ROUTE_BGP,
- Flags: flags,
- SAFI: zebra.SAFI_UNICAST,
- Message: msgFlags,
- Prefix: prefix,
- PrefixLength: uint8(plen),
- Nexthops: nexthops,
- Metric: med,
- },
- }
+ return &zebra.IPRouteBody{
+ Type: zebra.ROUTE_BGP,
+ Flags: flags,
+ SAFI: zebra.SAFI_UNICAST,
+ Message: msgFlags,
+ Prefix: prefix,
+ PrefixLength: uint8(plen),
+ Nexthops: nexthops,
+ Metric: med,
+ }, path.IsWithdraw
}
-func newNexthopRegisterMessage(dst pathList, version uint8, vrfId uint16, nhtManager *nexthopTrackingManager) *zebra.Message {
- // Note: NEXTHOP_REGISTER and NEXTHOP_UNREGISTER messages are not
- // supported in Zebra protocol version<3.
- if version < 3 || nhtManager == nil {
- return nil
+func newNexthopRegisterBody(dst pathList, nhtManager *nexthopTrackingManager) (*zebra.NexthopRegisterBody, bool) {
+ if nhtManager == nil {
+ return nil, false
}
paths := filterOutNilPath(dst)
if len(paths) == 0 {
- return nil
+ return nil, false
}
+ path := paths[0]
- route_family := paths[0].GetRouteFamily()
- command := zebra.NEXTHOP_REGISTER
- if paths[0].IsWithdraw == true {
+ if path.IsWithdraw == true {
// TODO:
// Send NEXTHOP_UNREGISTER message if the given nexthop is no longer
// referred by any path. Currently, do not send NEXTHOP_UNREGISTER
// message to simplify the implementation.
- //command = zebra.NEXTHOP_UNREGISTER
- return nil
+ return nil, true
}
+ family := path.GetRouteFamily()
nexthops := make([]*zebra.RegisteredNexthop, 0, len(paths))
for _, p := range paths {
nexthop := p.GetNexthop()
@@ -312,7 +289,7 @@ func newNexthopRegisterMessage(dst pathList, version uint8, vrfId uint16, nhtMan
}
var nh *zebra.RegisteredNexthop
- switch route_family {
+ switch family {
case bgp.RF_IPv4_UC, bgp.RF_IPv4_VPN:
nh = &zebra.RegisteredNexthop{
Family: syscall.AF_INET,
@@ -324,7 +301,7 @@ func newNexthopRegisterMessage(dst pathList, version uint8, vrfId uint16, nhtMan
Prefix: nexthop.To16(),
}
default:
- return nil
+ return nil, path.IsWithdraw
}
nexthops = append(nexthops, nh)
nhtManager.registerNexthop(nexthop)
@@ -333,36 +310,22 @@ func newNexthopRegisterMessage(dst pathList, version uint8, vrfId uint16, nhtMan
// If no nexthop needs to be registered or unregistered,
// skips to send message.
if len(nexthops) == 0 {
- return nil
+ return nil, path.IsWithdraw
}
- return &zebra.Message{
- Header: zebra.Header{
- Len: zebra.HeaderSize(version),
- Marker: zebra.HEADER_MARKER,
- Version: version,
- Command: command,
- VrfId: vrfId,
- },
- Body: &zebra.NexthopRegisterBody{
- Nexthops: nexthops,
- },
- }
+ return &zebra.NexthopRegisterBody{
+ Nexthops: nexthops,
+ }, path.IsWithdraw
}
func createPathFromIPRouteMessage(m *zebra.Message) *table.Path {
-
header := m.Header
body := m.Body.(*zebra.IPRouteBody)
- family := bgp.RF_IPv6_UC
- if header.Command == zebra.IPV4_ROUTE_ADD || header.Command == zebra.IPV4_ROUTE_DELETE {
- family = bgp.RF_IPv4_UC
- }
+ family := body.RouteFamily()
+ isWithdraw := body.IsWithdraw()
var nlri bgp.AddrPrefixInterface
pattr := make([]bgp.PathAttributeInterface, 0)
- var isWithdraw bool = header.Command == zebra.IPV4_ROUTE_DELETE || header.Command == zebra.IPV6_ROUTE_DELETE
-
origin := bgp.NewPathAttributeOrigin(bgp.BGP_ORIGIN_ATTR_TYPE_IGP)
pattr = append(pattr, origin)
@@ -468,7 +431,7 @@ func (z *zebraClient) loop() {
case <-z.dead:
return
case msg := <-z.client.Receive():
- switch msg.Body.(type) {
+ switch body := msg.Body.(type) {
case *zebra.IPRouteBody:
if p := createPathFromIPRouteMessage(msg); p != nil {
if _, err := z.server.AddPath("", pathList{p}); err != nil {
@@ -477,7 +440,6 @@ func (z *zebraClient) loop() {
}
case *zebra.NexthopUpdateBody:
if z.nhtManager != nil {
- body := msg.Body.(*zebra.NexthopUpdateBody)
if paths, err := createPathListFromNexthopUpdateMessage(msg, z.server.globalRib); err != nil {
log.Errorf("failed to create updated path list related to nexthop %s", body.Prefix.String())
} else {
@@ -489,11 +451,11 @@ func (z *zebraClient) loop() {
msg := ev.(*WatchEventBestPath)
if table.UseMultiplePaths.Enabled {
for _, dst := range msg.MultiPathList {
- if m := newIPRouteMessage(dst, z.client.Version, 0); m != nil {
- z.client.Send(m)
+ if body, isDelete := newIPRouteBody(dst); body != nil {
+ z.client.SendIPRoute(0, body, isDelete)
}
- if m := newNexthopRegisterMessage(dst, z.client.Version, 0, z.nhtManager); m != nil {
- z.client.Send(m)
+ if body, isUnregister := newNexthopRegisterBody(dst, z.nhtManager); body != nil {
+ z.client.SendNexthopRegister(0, body, isUnregister)
}
}
} else {
@@ -502,11 +464,11 @@ func (z *zebraClient) loop() {
path.VrfIds = []uint16{0}
}
for _, i := range path.VrfIds {
- if m := newIPRouteMessage(pathList{path}, z.client.Version, i); m != nil {
- z.client.Send(m)
+ if body, isWithdraw := newIPRouteBody(pathList{path}); body != nil {
+ z.client.SendIPRoute(i, body, isWithdraw)
}
- if m := newNexthopRegisterMessage(pathList{path}, z.client.Version, i, z.nhtManager); m != nil {
- z.client.Send(m)
+ if body, isWithdraw := newNexthopRegisterBody(pathList{path}, z.nhtManager); body != nil {
+ z.client.SendNexthopRegister(i, body, isWithdraw)
}
}
}
@@ -520,20 +482,20 @@ func newZebraClient(s *BgpServer, url string, protos []string, version uint8, nh
if len(l) != 2 {
return nil, fmt.Errorf("unsupported url: %s", url)
}
- cli, err := zebra.NewClient(l[0], l[1], zebra.ROUTE_BGP, version)
- if err != nil {
- // Retry with another Zebra message version
- var retry_version uint8 = 2
- if version == 2 {
- retry_version = 3
+ var cli *zebra.Client
+ var err error
+ for _, ver := range []uint8{version, 2, 3, 4} {
+ cli, err = zebra.NewClient(l[0], l[1], zebra.ROUTE_BGP, ver)
+ if err == nil {
+ break
}
+ // Retry with another Zebra message version
log.WithFields(log.Fields{
"Topic": "Zebra",
- }).Warnf("cannot connect to Zebra with message version %d. retry with version %d", version, retry_version)
- cli, err = zebra.NewClient(l[0], l[1], zebra.ROUTE_BGP, retry_version)
- if err != nil {
- return nil, err
- }
+ }).Warnf("cannot connect to Zebra with message version %d. going to retry another version...", ver)
+ }
+ if cli == nil {
+ return nil, err
}
// Note: HELLO/ROUTER_ID_ADD messages are automatically sent to negotiate
// the Zebra message version in zebra.NewClient().
diff --git a/server/zclient_test.go b/server/zclient_test.go
index d15155c9..ac20a0f4 100644
--- a/server/zclient_test.go
+++ b/server/zclient_test.go
@@ -24,9 +24,10 @@ import (
"time"
)
-func Test_createRequestFromIPRouteMessage(t *testing.T) {
+func Test_createPathFromIPRouteMessage(t *testing.T) {
assert := assert.New(t)
+ // IPv4 Route Add
m := &zebra.Message{}
h := &zebra.Header{
Len: zebra.HeaderSize(2),
@@ -34,7 +35,6 @@ func Test_createRequestFromIPRouteMessage(t *testing.T) {
Version: 2,
Command: zebra.IPV4_ROUTE_ADD,
}
-
b := &zebra.IPRouteBody{
Type: zebra.ROUTE_TYPE(zebra.ROUTE_STATIC),
Flags: zebra.FLAG(zebra.FLAG_SELECTED),
@@ -49,7 +49,6 @@ func Test_createRequestFromIPRouteMessage(t *testing.T) {
Mtu: uint32(0),
Api: zebra.API_TYPE(zebra.IPV4_ROUTE_ADD),
}
-
m.Header = *h
m.Body = b
@@ -61,9 +60,12 @@ func Test_createRequestFromIPRouteMessage(t *testing.T) {
assert.True(pp.IsFromExternal())
assert.False(pp.IsWithdraw)
- // withdraw
+ // IPv4 Route Delete
h.Command = zebra.IPV4_ROUTE_DELETE
+ b.Api = zebra.IPV4_ROUTE_DELETE
m.Header = *h
+ m.Body = b
+
path = createPathFromIPRouteMessage(m)
pp = table.NewPath(nil, path.GetNlri(), path.IsWithdraw, path.GetPathAttrs(), time.Now(), false)
pp.SetIsFromExternal(path.IsFromExternal())
@@ -74,8 +76,9 @@ func Test_createRequestFromIPRouteMessage(t *testing.T) {
assert.True(pp.IsFromExternal())
assert.True(pp.IsWithdraw)
- // IPv6
+ // IPv6 Route Add
h.Command = zebra.IPV6_ROUTE_ADD
+ b.Api = zebra.IPV6_ROUTE_ADD
b.Prefix = net.ParseIP("2001:db8:0:f101::")
b.PrefixLength = uint8(64)
b.Nexthops = []net.IP{net.ParseIP("::")}
@@ -92,9 +95,12 @@ func Test_createRequestFromIPRouteMessage(t *testing.T) {
assert.True(pp.IsFromExternal())
assert.False(pp.IsWithdraw)
- // withdraw
+ // IPv6 Route Delete
h.Command = zebra.IPV6_ROUTE_DELETE
+ b.Api = zebra.IPV6_ROUTE_DELETE
m.Header = *h
+ m.Body = b
+
path = createPathFromIPRouteMessage(m)
pp = table.NewPath(nil, path.GetNlri(), path.IsWithdraw, path.GetPathAttrs(), time.Now(), false)
pp.SetIsFromExternal(path.IsFromExternal())