summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/grpc_server.go2
-rw-r--r--api/util.go123
-rw-r--r--gobgp/cmd/common.go103
-rw-r--r--gobgp/cmd/global_test.go5
-rw-r--r--gobgp/cmd/monitor.go6
-rw-r--r--gobgp/cmd/neighbor.go148
-rw-r--r--openswitch/openswitch.go134
-rw-r--r--table/destination.go9
-rw-r--r--table/path.go25
-rw-r--r--table/table.go14
-rw-r--r--test/lib/gobgp.py20
-rw-r--r--test/scenario_test/bgp_router_test.py8
-rw-r--r--test/scenario_test/graceful_restart_test.py2
-rw-r--r--test/scenario_test/monitor_test.py2
14 files changed, 311 insertions, 290 deletions
diff --git a/api/grpc_server.go b/api/grpc_server.go
index 225c3971..a850100c 100644
--- a/api/grpc_server.go
+++ b/api/grpc_server.go
@@ -251,7 +251,7 @@ func (s *Server) GetRib(ctx context.Context, arg *GetRibRequest) (*GetRibRespons
}
dsts := []*Destination{}
- for _, dst := range tbl.GetSortedDestinations() {
+ for _, dst := range tbl.GetDestinations() {
dsts = append(dsts, &Destination{
Prefix: dst.GetNlri().String(),
Paths: func(paths []*table.Path) []*Path {
diff --git a/api/util.go b/api/util.go
new file mode 100644
index 00000000..373bad47
--- /dev/null
+++ b/api/util.go
@@ -0,0 +1,123 @@
+// Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package gobgpapi
+
+import (
+ "fmt"
+ "net"
+ "time"
+
+ "github.com/osrg/gobgp/config"
+ "github.com/osrg/gobgp/packet/bgp"
+ "github.com/osrg/gobgp/table"
+)
+
+type ToNativeOption struct {
+ LocalAS uint32
+ LocalID net.IP
+ RouteReflectorClient bool
+ RouteReflectorClusterID net.IP
+ NLRI bgp.AddrPrefixInterface
+}
+
+func (t *Table) ToNativeTable(option ...ToNativeOption) (*table.Table, error) {
+ dsts := make([]*table.Destination, 0, len(t.Destinations))
+ for _, d := range t.Destinations {
+ dst, err := d.ToNativeDestination(option...)
+ if err != nil {
+ return nil, err
+ }
+ dsts = append(dsts, dst)
+ }
+ return table.NewTable(bgp.RouteFamily(t.Family), dsts...), nil
+}
+
+func getNLRI(family bgp.RouteFamily, buf []byte) (bgp.AddrPrefixInterface, error) {
+ afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(family))
+ nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi)
+ if err != nil {
+ return nil, err
+ }
+ if err := nlri.DecodeFromBytes(buf); err != nil {
+ return nil, err
+ }
+ return nlri, nil
+}
+
+func (d *Destination) ToNativeDestination(option ...ToNativeOption) (*table.Destination, error) {
+ if len(d.Paths) == 0 {
+ return nil, fmt.Errorf("no path in destination")
+ }
+ nlri, err := getNLRI(bgp.RouteFamily(d.Paths[0].Family), d.Paths[0].Nlri)
+ if err != nil {
+ return nil, err
+ }
+ option = append(option, ToNativeOption{
+ NLRI: nlri,
+ })
+ paths := make([]*table.Path, 0, len(d.Paths))
+ for _, p := range d.Paths {
+ path, err := p.ToNativePath(option...)
+ if err != nil {
+ return nil, err
+ }
+ paths = append(paths, path)
+ }
+ return table.NewDestination(nlri, paths...), nil
+}
+
+func (p *Path) ToNativePath(option ...ToNativeOption) (*table.Path, error) {
+ info := &table.PeerInfo{
+ AS: p.SourceAsn,
+ ID: net.ParseIP(p.SourceId),
+ Address: net.ParseIP(p.NeighborIp),
+ }
+ var nlri bgp.AddrPrefixInterface
+ for _, o := range option {
+ info.LocalAS = o.LocalAS
+ info.LocalID = o.LocalID
+ info.RouteReflectorClient = o.RouteReflectorClient
+ info.RouteReflectorClusterID = o.RouteReflectorClusterID
+ nlri = o.NLRI
+ }
+ if nlri == nil {
+ var err error
+ nlri, err = getNLRI(bgp.RouteFamily(p.Family), p.Nlri)
+ if err != nil {
+ return nil, err
+ }
+ }
+ pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs))
+ for _, attr := range p.Pattrs {
+ p, err := bgp.GetPathAttribute(attr)
+ if err != nil {
+ return nil, err
+ }
+ err = p.DecodeFromBytes(attr)
+ if err != nil {
+ return nil, err
+ }
+ pattr = append(pattr, p)
+ }
+ t := time.Unix(p.Age, 0)
+ path := table.NewPath(info, nlri, p.IsWithdraw, pattr, t, false)
+ path.SetValidation(config.IntToRpkiValidationResultTypeMap[int(p.Validation)])
+ path.MarkStale(p.Stale)
+ if p.Filtered {
+ path.Filter("", table.POLICY_DIRECTION_IN)
+ }
+ return path, nil
+}
diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go
index e1d58b96..09965803 100644
--- a/gobgp/cmd/common.go
+++ b/gobgp/cmd/common.go
@@ -138,109 +138,6 @@ func cidr2prefix(cidr string) string {
return buffer.String()[:ones]
}
-type Destination struct {
- Prefix string `json:"prefix"`
- Paths []*Path `json:"paths"`
-}
-
-func ApiStruct2Destination(dst *gobgpapi.Destination) (*Destination, error) {
- paths := make([]*Path, 0, len(dst.Paths))
- for _, p := range dst.Paths {
- ps, err := ApiStruct2Path(p)
- if err != nil {
- return nil, err
- }
- paths = append(paths, ps...)
- }
- return &Destination{
- Prefix: dst.Prefix,
- Paths: paths,
- }, nil
-
-}
-
-type Path struct {
- Nlri bgp.AddrPrefixInterface `json:"nlri"`
- PathAttrs []bgp.PathAttributeInterface `json:"attrs"`
- Age int64 `json:"age"`
- Best bool `json:"best"`
- IsWithdraw bool `json:"isWithdraw"`
- Validation int32 `json:"validation"`
- Filtered bool `json:"filtered"`
- SourceId string `json:"source-id"`
- NeighborIp string `json:"neighbor-ip"`
- Stale bool `json:"stale"`
-}
-
-func ApiStruct2Path(p *gobgpapi.Path) ([]*Path, error) {
- nlris := make([]bgp.AddrPrefixInterface, 0, 1)
- if len(p.Nlri) == 0 {
- return nil, fmt.Errorf("path doesn't have nlri")
- }
- afi, safi := bgp.RouteFamilyToAfiSafi(bgp.RouteFamily(p.Family))
- nlri, err := bgp.NewPrefixFromRouteFamily(afi, safi)
- if err != nil {
- return nil, err
- }
-
- if err := nlri.DecodeFromBytes(p.Nlri); err != nil {
- return nil, err
- }
- nlris = append(nlris, nlri)
-
- pattr := make([]bgp.PathAttributeInterface, 0, len(p.Pattrs))
- for _, attr := range p.Pattrs {
- p, err := bgp.GetPathAttribute(attr)
- if err != nil {
- return nil, err
- }
-
- err = p.DecodeFromBytes(attr)
- if err != nil {
- return nil, err
- }
- pattr = append(pattr, p)
- }
-
- paths := make([]*Path, 0, len(nlris))
- for _, nlri := range nlris {
- paths = append(paths, &Path{
- Nlri: nlri,
- PathAttrs: pattr,
- Age: p.Age,
- Best: p.Best,
- IsWithdraw: p.IsWithdraw,
- Validation: p.Validation,
- SourceId: p.SourceId,
- NeighborIp: p.NeighborIp,
- Filtered: p.Filtered,
- Stale: p.Stale,
- })
- }
- return paths, nil
-}
-
-type paths []*Path
-
-func (p paths) Len() int {
- return len(p)
-}
-
-func (p paths) Swap(i, j int) {
- p[i], p[j] = p[j], p[i]
-}
-
-func (p paths) Less(i, j int) bool {
- if p[i].Nlri.String() == p[j].Nlri.String() {
- if p[i].Best {
- return true
- }
- }
- strings := sort.StringSlice{cidr2prefix(p[i].Nlri.String()),
- cidr2prefix(p[j].Nlri.String())}
- return strings.Less(0, 1)
-}
-
func extractReserved(args, keys []string) map[string][]string {
m := make(map[string][]string, len(keys))
var k string
diff --git a/gobgp/cmd/global_test.go b/gobgp/cmd/global_test.go
index 8dc8171c..c41f4c56 100644
--- a/gobgp/cmd/global_test.go
+++ b/gobgp/cmd/global_test.go
@@ -31,11 +31,10 @@ func Test_ParsePath(t *testing.T) {
assert.Nil(err)
fmt.Println(path)
path.Family = uint32(bgp.RF_IPv4_UC)
- paths, err := ApiStruct2Path(path)
+ p, err := path.ToNativePath()
assert.Nil(err)
- assert.True(len(paths) == 1)
i := 0
- for _, a := range paths[0].PathAttrs {
+ for _, a := range p.GetPathAttrs() {
assert.True(i < int(a.GetType()))
i = int(a.GetType())
}
diff --git a/gobgp/cmd/monitor.go b/gobgp/cmd/monitor.go
index 4cb95ece..dd45901e 100644
--- a/gobgp/cmd/monitor.go
+++ b/gobgp/cmd/monitor.go
@@ -40,16 +40,16 @@ func NewMonitorCmd() *cobra.Command {
} else if err != nil {
exitWithError(err)
}
- p, err := ApiStruct2Path(d.Paths[0])
+ dst, err := d.ToNativeDestination()
if err != nil {
exitWithError(err)
}
if globalOpts.Json {
- j, _ := json.Marshal(p)
+ j, _ := json.Marshal(dst.GetAllKnownPathList())
fmt.Println(string(j))
} else {
- ShowRoute(p, false, false, false, true, false)
+ ShowRoute(dst.GetAllKnownPathList(), false, false, false, true, false)
}
}
}
diff --git a/gobgp/cmd/neighbor.go b/gobgp/cmd/neighbor.go
index 43c4a8aa..4def24ec 100644
--- a/gobgp/cmd/neighbor.go
+++ b/gobgp/cmd/neighbor.go
@@ -21,6 +21,7 @@ import (
api "github.com/osrg/gobgp/api"
"github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet/bgp"
+ "github.com/osrg/gobgp/table"
"github.com/spf13/cobra"
"golang.org/x/net/context"
"net"
@@ -310,7 +311,7 @@ type AsPathFormat struct {
separator string
}
-func ShowRoute(pathList []*Path, showAge, showBest, showLabel, isMonitor, printHeader bool) {
+func ShowRoute(pathList []*table.Path, showAge, showBest, showLabel, isMonitor, printHeader bool) {
var pathStrs [][]interface{}
maxPrefixLen := 20
@@ -319,25 +320,17 @@ func ShowRoute(pathList []*Path, showAge, showBest, showLabel, isMonitor, printH
maxLabelLen := 10
now := time.Now()
- for _, p := range pathList {
- var nexthop string
- var aspathstr string
+ for idx, p := range pathList {
+ nexthop := "fictitious"
+ if n := p.GetNexthop(); n != nil {
+ nexthop = p.GetNexthop().String()
+ }
+ aspathstr := p.GetAsString()
s := []string{}
- for _, a := range p.PathAttrs {
+ for _, a := range p.GetPathAttrs() {
switch a.GetType() {
- case bgp.BGP_ATTR_TYPE_NEXT_HOP:
- nexthop = a.(*bgp.PathAttributeNextHop).Value.String()
- case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
- n := a.(*bgp.PathAttributeMpReachNLRI).Nexthop
- if n != nil {
- nexthop = n.String()
- } else {
- nexthop = "fictitious"
- }
- case bgp.BGP_ATTR_TYPE_AS_PATH:
- aspathstr = a.String()
- case bgp.BGP_ATTR_TYPE_AS4_PATH:
+ case bgp.BGP_ATTR_TYPE_NEXT_HOP, bgp.BGP_ATTR_TYPE_MP_REACH_NLRI, bgp.BGP_ATTR_TYPE_AS_PATH, bgp.BGP_ATTR_TYPE_AS4_PATH:
continue
default:
s = append(s, a.String())
@@ -354,27 +347,27 @@ func ShowRoute(pathList []*Path, showAge, showBest, showLabel, isMonitor, printH
}
best := ""
- if p.Stale {
+ if p.IsStale() {
best += "S"
}
- switch int(p.Validation) {
- case config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND.ToInt():
+ switch p.Validation() {
+ case config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND:
best += "N"
- case config.RPKI_VALIDATION_RESULT_TYPE_VALID.ToInt():
+ case config.RPKI_VALIDATION_RESULT_TYPE_VALID:
best += "V"
- case config.RPKI_VALIDATION_RESULT_TYPE_INVALID.ToInt():
+ case config.RPKI_VALIDATION_RESULT_TYPE_INVALID:
best += "I"
}
if showBest {
- if p.Best {
+ if idx == 0 {
best += "*>"
} else {
best += "* "
}
}
- nlri := p.Nlri.String()
- if maxPrefixLen < len(nlri) {
- maxPrefixLen = len(nlri)
+ nlri := p.GetNlri()
+ if maxPrefixLen < len(nlri.String()) {
+ maxPrefixLen = len(nlri.String())
}
if isMonitor {
@@ -387,15 +380,15 @@ func ShowRoute(pathList []*Path, showAge, showBest, showLabel, isMonitor, printH
args := []interface{}{best, nlri}
if showLabel {
label := ""
- switch p.Nlri.(type) {
+ switch nlri.(type) {
case *bgp.LabeledIPAddrPrefix:
- label = p.Nlri.(*bgp.LabeledIPAddrPrefix).Labels.String()
+ label = nlri.(*bgp.LabeledIPAddrPrefix).Labels.String()
case *bgp.LabeledIPv6AddrPrefix:
- label = p.Nlri.(*bgp.LabeledIPv6AddrPrefix).Labels.String()
+ label = nlri.(*bgp.LabeledIPv6AddrPrefix).Labels.String()
case *bgp.LabeledVPNIPAddrPrefix:
- label = p.Nlri.(*bgp.LabeledVPNIPAddrPrefix).Labels.String()
+ label = nlri.(*bgp.LabeledVPNIPAddrPrefix).Labels.String()
case *bgp.LabeledVPNIPv6AddrPrefix:
- label = p.Nlri.(*bgp.LabeledVPNIPv6AddrPrefix).Labels.String()
+ label = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).Labels.String()
}
if maxLabelLen < len(label) {
maxLabelLen = len(label)
@@ -404,7 +397,7 @@ func ShowRoute(pathList []*Path, showAge, showBest, showLabel, isMonitor, printH
}
args = append(args, []interface{}{nexthop, aspathstr}...)
if showAge {
- args = append(args, formatTimedelta(int64(now.Sub(time.Unix(int64(p.Age), 0)).Seconds())))
+ args = append(args, formatTimedelta(int64(now.Sub(p.GetTimestamp()).Seconds())))
}
args = append(args, pattrstr)
pathStrs = append(pathStrs, args)
@@ -514,10 +507,9 @@ func showNeighborRib(r string, name string, args []string) error {
if err != nil {
return err
}
- rib := rsp.Table
switch r {
case CMD_LOCAL, CMD_ADJ_IN, CMD_ACCEPTED, CMD_REJECTED, CMD_ADJ_OUT:
- if len(rib.Destinations) == 0 {
+ if len(rsp.Table.Destinations) == 0 {
peer, err := getNeighbor(name)
if err != nil {
return err
@@ -528,84 +520,48 @@ func showNeighborRib(r string, name string, args []string) error {
}
}
- isResultSorted := func(rf bgp.RouteFamily) bool {
- switch rf {
- case bgp.RF_IPv4_UC, bgp.RF_IPv6_UC, bgp.RF_FS_IPv4_UC, bgp.RF_FS_IPv6_UC, bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN, bgp.RF_FS_L2_VPN:
- return true
- }
- return false
+ rib, err := rsp.Table.ToNativeTable()
+ if err != nil {
+ return err
+ }
+
+ if globalOpts.Json {
+ j, _ := json.Marshal(rib.GetDestinations())
+ fmt.Println(string(j))
+ return nil
}
- dsts := []*Destination{}
counter := 0
- for _, d := range rib.Destinations {
- dst, err := ApiStruct2Destination(d)
- if err != nil {
- return err
- }
- if isResultSorted(rf) && !globalOpts.Json && len(dst.Paths) > 0 {
- ps := paths{}
- for _, p := range dst.Paths {
+ for _, d := range rib.GetSortedDestinations() {
+ var ps []*table.Path
+ if r == CMD_ACCEPTED || r == CMD_REJECTED {
+ for _, p := range d.GetAllKnownPathList() {
switch r {
case CMD_ACCEPTED:
- if !p.Filtered {
- ps = append(ps, p)
+ if p.Filtered("") > table.POLICY_DIRECTION_NONE {
+ continue
}
case CMD_REJECTED:
- if p.Filtered {
- ps = append(ps, p)
+ if p.Filtered("") == table.POLICY_DIRECTION_NONE {
+ continue
}
- default:
- ps = append(ps, p)
}
- }
- sort.Sort(ps)
- if counter == 0 {
- ShowRoute(ps, showAge, showBest, showLabel, false, true)
- } else {
- ShowRoute(ps, showAge, showBest, showLabel, false, false)
- }
- counter++
- }
- dsts = append(dsts, dst)
- }
-
- if globalOpts.Json {
- j, _ := json.Marshal(dsts)
- fmt.Println(string(j))
- return nil
- }
-
- if isResultSorted(rf) && counter != 0 {
- // we already showed
- return nil
- }
-
- ps := paths{}
- for _, dst := range dsts {
- for _, p := range dst.Paths {
- switch r {
- case CMD_ACCEPTED:
- if !p.Filtered {
- ps = append(ps, p)
- }
- case CMD_REJECTED:
- if p.Filtered {
- ps = append(ps, p)
- }
- default:
ps = append(ps, p)
}
+ } else {
+ ps = d.GetAllKnownPathList()
}
+ if counter == 0 {
+ ShowRoute(ps, showAge, showBest, showLabel, false, true)
+ } else {
+ ShowRoute(ps, showAge, showBest, showLabel, false, false)
+ }
+ counter++
}
- if len(ps) == 0 {
+ if counter == 0 {
fmt.Println("Network not in table")
- return nil
}
-
- sort.Sort(ps)
- ShowRoute(ps, showAge, showBest, showLabel, false, true)
return nil
}
diff --git a/openswitch/openswitch.go b/openswitch/openswitch.go
index 4f6d7e0c..7641a9b2 100644
--- a/openswitch/openswitch.go
+++ b/openswitch/openswitch.go
@@ -24,8 +24,8 @@ import (
log "github.com/Sirupsen/logrus"
api "github.com/osrg/gobgp/api"
- "github.com/osrg/gobgp/gobgp/cmd"
"github.com/osrg/gobgp/packet/bgp"
+ "github.com/osrg/gobgp/table"
"github.com/satori/go.uuid"
ovsdb "github.com/socketplane/libovsdb"
"golang.org/x/net/context"
@@ -403,63 +403,60 @@ func (m *OpsManager) handleRouteUpdate(cli api.GobgpApiClient, update ovsdb.Tabl
}
}
-func parseRouteToOps(pl []*cmd.Path) (map[string]interface{}, bool, error) {
+func parseRouteToOps(p *table.Path) (map[string]interface{}, bool, error) {
route := map[string]interface{}{"metric": 0, "peer": "Remote announcement"}
IsWithdraw := false
- for _, p := range pl {
- var nexthop string
- pathAttr := map[string]string{"BGP_iBGP": "false",
- "BGP_flags": "16",
- "BGP_internal": "false",
- "BGP_loc_pref": "0",
- "IsFromGobgp": "true",
- }
- for _, a := range p.PathAttrs {
- switch a.GetType() {
- case bgp.BGP_ATTR_TYPE_NEXT_HOP:
- nexthop = a.(*bgp.PathAttributeNextHop).Value.String()
- case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
- n := a.(*bgp.PathAttributeMpReachNLRI).Nexthop
- if n != nil {
- nexthop = n.String()
- } else {
- nexthop = ""
- }
- case bgp.BGP_ATTR_TYPE_AS_PATH:
- pathAttr["BGP_AS_path"] = a.(*bgp.PathAttributeAsPath).String()
- case bgp.BGP_ATTR_TYPE_ORIGIN:
- origin := "-"
- switch a.(*bgp.PathAttributeOrigin).Value[0] {
- case bgp.BGP_ORIGIN_ATTR_TYPE_IGP:
- origin = "i"
- case bgp.BGP_ORIGIN_ATTR_TYPE_EGP:
- origin = "e"
- case bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE:
- origin = "?"
- }
- pathAttr["BGP_origin"] = origin
- case bgp.BGP_ATTR_TYPE_LOCAL_PREF:
- pathAttr["BGP_loc_pref"] = fmt.Sprintf("%v", a.(*bgp.PathAttributeLocalPref).Value)
- case bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC:
- route["metric"] = a.(*bgp.PathAttributeMultiExitDisc).Value
- default:
- continue
+ var nexthop string
+ pathAttr := map[string]string{"BGP_iBGP": "false",
+ "BGP_flags": "16",
+ "BGP_internal": "false",
+ "BGP_loc_pref": "0",
+ "IsFromGobgp": "true",
+ }
+ for _, a := range p.GetPathAttrs() {
+ switch a.GetType() {
+ case bgp.BGP_ATTR_TYPE_NEXT_HOP:
+ nexthop = a.(*bgp.PathAttributeNextHop).Value.String()
+ case bgp.BGP_ATTR_TYPE_MP_REACH_NLRI:
+ n := a.(*bgp.PathAttributeMpReachNLRI).Nexthop
+ if n != nil {
+ nexthop = n.String()
+ } else {
+ nexthop = ""
}
+ case bgp.BGP_ATTR_TYPE_AS_PATH:
+ pathAttr["BGP_AS_path"] = a.(*bgp.PathAttributeAsPath).String()
+ case bgp.BGP_ATTR_TYPE_ORIGIN:
+ origin := "-"
+ switch a.(*bgp.PathAttributeOrigin).Value[0] {
+ case bgp.BGP_ORIGIN_ATTR_TYPE_IGP:
+ origin = "i"
+ case bgp.BGP_ORIGIN_ATTR_TYPE_EGP:
+ origin = "e"
+ case bgp.BGP_ORIGIN_ATTR_TYPE_INCOMPLETE:
+ origin = "?"
+ }
+ pathAttr["BGP_origin"] = origin
+ case bgp.BGP_ATTR_TYPE_LOCAL_PREF:
+ pathAttr["BGP_loc_pref"] = fmt.Sprintf("%v", a.(*bgp.PathAttributeLocalPref).Value)
+ case bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC:
+ route["metric"] = a.(*bgp.PathAttributeMultiExitDisc).Value
+ default:
+ continue
}
- IsWithdraw = p.IsWithdraw
- afi := "ipv4"
- if p.Nlri.AFI() != bgp.AFI_IP {
- afi = "ipv6"
- }
- safi := "unicast"
-
- route["prefix"] = p.Nlri.String()
- route["address_family"] = afi
- route["sub_address_family"] = safi
- route["bgp_nexthops"] = nexthop
- route["path_attributes"] = pathAttr
- break
}
+ IsWithdraw = p.IsWithdraw
+ afi := "ipv4"
+ if p.GetNlri().AFI() != bgp.AFI_IP {
+ afi = "ipv6"
+ }
+ safi := "unicast"
+
+ route["prefix"] = p.GetNlri().String()
+ route["address_family"] = afi
+ route["sub_address_family"] = safi
+ route["bgp_nexthops"] = nexthop
+ route["path_attributes"] = pathAttr
return route, IsWithdraw, nil
}
@@ -512,7 +509,7 @@ func deleteRoute(opsRoute map[string]interface{}) ovsdb.Operation {
return deleteOp
}
-func (m *OpsManager) TransactPreparation(p []*cmd.Path) (*OpsOperation, error) {
+func (m *OpsManager) TransactPreparation(p *table.Path) (*OpsOperation, error) {
v, err := m.getVrfUUID()
if err != nil {
return nil, err
@@ -571,25 +568,38 @@ func (m *OpsManager) GobgpMonitor(target string) {
log.Fatal(err)
}
cli := api.NewGobgpApiClient(conn)
+ rsp, err := cli.GetServer(context.Background(), &api.GetServerRequest{})
+ if err != nil {
+ log.Fatal(err)
+ }
+ nativeOption := api.ToNativeOption{
+ LocalAS: uint32(rsp.Global.As),
+ LocalID: net.ParseIP(rsp.Global.RouterId),
+ }
stream, err := cli.MonitorRib(context.Background(), &api.Table{
Type: api.Resource_GLOBAL,
Family: uint32(bgp.RF_IPv4_UC),
})
+ if err != nil {
+ log.Fatal(err)
+ }
for {
d, err := stream.Recv()
- bPath := d.Paths[0]
- if bPath.IsFromExternal && !bPath.IsWithdraw {
- continue
+ if err != nil {
+ log.Fatal(err)
}
- p, err := cmd.ApiStruct2Path(bPath)
+ dst, err := d.ToNativeDestination(nativeOption)
if err != nil {
log.WithFields(log.Fields{
"Topic": "openswitch",
- "Type": "MonitorRequest",
- "Error": err,
- }).Error("failed parse path of gobgp")
+ }).Error(err)
+ continue
+ }
+ path := dst.GetAllKnownPathList()[0]
+ if path.IsLocal() && !path.IsWithdraw {
+ continue
}
- o, err := m.TransactPreparation(p)
+ o, err := m.TransactPreparation(path)
if err != nil {
log.WithFields(log.Fields{
"Topic": "openswitch",
diff --git a/table/destination.go b/table/destination.go
index 7e0deb2b..3a1c1c45 100644
--- a/table/destination.go
+++ b/table/destination.go
@@ -18,6 +18,7 @@ package table
import (
"bytes"
"encoding/binary"
+ "encoding/json"
"fmt"
"net"
"sort"
@@ -124,11 +125,11 @@ type Destination struct {
RadixKey string
}
-func NewDestination(nlri bgp.AddrPrefixInterface) *Destination {
+func NewDestination(nlri bgp.AddrPrefixInterface, known ...*Path) *Destination {
d := &Destination{
routeFamily: bgp.AfiSafiToRouteFamily(nlri.AFI(), nlri.SAFI()),
nlri: nlri,
- knownPathList: make([]*Path, 0),
+ knownPathList: known,
withdrawList: make([]*Path, 0),
newPathList: make([]*Path, 0),
}
@@ -856,6 +857,10 @@ type DestinationSelectOption struct {
adj bool
}
+func (d *Destination) MarshalJSON() ([]byte, error) {
+ return json.Marshal(d.GetAllKnownPathList())
+}
+
func (old *Destination) Select(option ...DestinationSelectOption) *Destination {
id := GLOBAL_RIB_NAME
var vrf *Vrf
diff --git a/table/path.go b/table/path.go
index c75ca579..0aab6004 100644
--- a/table/path.go
+++ b/table/path.go
@@ -17,6 +17,7 @@ package table
import (
"bytes"
+ "encoding/json"
"fmt"
"math"
"net"
@@ -845,6 +846,30 @@ func (lhs *Path) Equal(rhs *Path) bool {
return bytes.Equal(pattrs(lhs.GetPathAttrs()), pattrs(rhs.GetPathAttrs()))
}
+func (path *Path) MarshalJSON() ([]byte, error) {
+ return json.Marshal(struct {
+ Nlri bgp.AddrPrefixInterface `json:"nlri"`
+ PathAttrs []bgp.PathAttributeInterface `json:"attrs"`
+ Age int64 `json:"age"`
+ Withdrawal bool `json:"withdrawal,omitempty"`
+ Validation string `json:"validation,omitempty"`
+ SourceID net.IP `json:"source-id,omitempty"`
+ NeighborIP net.IP `json:"neighbor-ip,omitempty"`
+ Stale bool `json:"stale,omitempty"`
+ Filtered bool `json:"filtered,omitempty"`
+ }{
+ Nlri: path.GetNlri(),
+ PathAttrs: path.GetPathAttrs(),
+ Age: path.GetTimestamp().Unix(),
+ Withdrawal: path.IsWithdraw,
+ Validation: string(path.Validation()),
+ SourceID: path.GetSource().ID,
+ NeighborIP: path.GetSource().Address,
+ Stale: path.IsStale(),
+ Filtered: path.Filtered("") > POLICY_DIRECTION_NONE,
+ })
+}
+
func (lhs *Path) Compare(rhs *Path) int {
if lhs.IsLocal() && !rhs.IsLocal() {
return 1
diff --git a/table/table.go b/table/table.go
index bad0e824..f89e8dff 100644
--- a/table/table.go
+++ b/table/table.go
@@ -50,10 +50,14 @@ type Table struct {
destinations map[string]*Destination
}
-func NewTable(rf bgp.RouteFamily) *Table {
+func NewTable(rf bgp.RouteFamily, dsts ...*Destination) *Table {
+ destinations := make(map[string]*Destination)
+ for _, dst := range dsts {
+ destinations[dst.GetNlri().String()] = dst
+ }
return &Table{
routeFamily: rf,
- destinations: make(map[string]*Destination),
+ destinations: destinations,
}
}
@@ -229,15 +233,11 @@ func (t *Table) GetSortedDestinations() []*Destination {
results = append(results, v.(*Destination))
return false
})
- case bgp.RF_FS_IPv4_UC, bgp.RF_FS_IPv6_UC, bgp.RF_FS_IPv4_VPN, bgp.RF_FS_IPv6_VPN, bgp.RF_FS_L2_VPN:
- for _, dst := range t.GetDestinations() {
- results = append(results, dst)
- }
- sort.Sort(destinations(results))
default:
for _, dst := range t.GetDestinations() {
results = append(results, dst)
}
+ sort.Sort(destinations(results))
}
return results
}
diff --git a/test/lib/gobgp.py b/test/lib/gobgp.py
index d16610f0..316e8535 100644
--- a/test/lib/gobgp.py
+++ b/test/lib/gobgp.py
@@ -121,23 +121,29 @@ class GoBGPContainer(BGPContainer):
cmd = 'gobgp -j neighbor {0} local {1} -a {2}'.format(peer_addr, prefix, rf)
output = self.local(cmd, capture=True)
ret = json.loads(output)
- for d in ret:
- for p in d["paths"]:
+ dsts = []
+ for k, v in ret.iteritems():
+ for p in v:
p["nexthop"] = self._get_nexthop(p)
p["aspath"] = self._get_as_path(p)
p["local-pref"] = self._get_local_pref(p)
- return ret
+ p["prefix"] = k
+ dsts.append({'paths': v, 'prefix': k})
+ return dsts
def get_global_rib(self, prefix='', rf='ipv4'):
cmd = 'gobgp -j global rib {0} -a {1}'.format(prefix, rf)
output = self.local(cmd, capture=True)
ret = json.loads(output)
- for d in ret:
- for p in d["paths"]:
+ dsts = []
+ for k, v in ret.iteritems():
+ for p in v:
p["nexthop"] = self._get_nexthop(p)
p["aspath"] = self._get_as_path(p)
p["local-pref"] = self._get_local_pref(p)
- return ret
+ p["prefix"] = k
+ dsts.append({'paths': v, 'prefix': k})
+ return dsts
def monitor_global_rib(self, queue, rf='ipv4'):
host = self.ip_addrs[0][1].split('/')[0]
@@ -168,7 +174,7 @@ class GoBGPContainer(BGPContainer):
adj_type,
prefix, rf)
output = self.local(cmd, capture=True)
- ret = [p["paths"][0] for p in json.loads(output)]
+ ret = [p[0] for p in json.loads(output).itervalues()]
for p in ret:
p["nexthop"] = self._get_nexthop(p)
p["aspath"] = self._get_as_path(p)
diff --git a/test/scenario_test/bgp_router_test.py b/test/scenario_test/bgp_router_test.py
index f6831f79..3154df21 100644
--- a/test/scenario_test/bgp_router_test.py
+++ b/test/scenario_test/bgp_router_test.py
@@ -333,10 +333,10 @@ class GoBGPTestBase(unittest.TestCase):
paths = g1.get_adj_rib_out(q1, '30.0.0.0/24')
self.assertTrue(len(paths) == 1)
- self.assertTrue(paths[0]['source-id'] == '<nil>')
+ self.assertTrue('source-id' not in paths[0])
paths = g1.get_adj_rib_out(q2, '30.0.0.0/24')
self.assertTrue(len(paths) == 1)
- self.assertTrue(paths[0]['source-id'] == '<nil>')
+ self.assertTrue('source-id' not in paths[0])
g1.local('gobgp global rib del 30.0.0.0/24')
@@ -405,8 +405,8 @@ class GoBGPTestBase(unittest.TestCase):
cnt2 = 0
g = next_prefix()
n = g.next()
- for path in g1.get_global_rib():
- if path['prefix'] == n:
+ for path in g1.local("gobgp global rib", capture=True).split('\n')[1:]:
+ if [elem for elem in path.split(' ') if elem != ''][1] == n:
try:
cnt2 += 1
n = g.next()
diff --git a/test/scenario_test/graceful_restart_test.py b/test/scenario_test/graceful_restart_test.py
index 9b97b82b..6f0f4211 100644
--- a/test/scenario_test/graceful_restart_test.py
+++ b/test/scenario_test/graceful_restart_test.py
@@ -82,7 +82,7 @@ class GoBGPTestBase(unittest.TestCase):
self.assertTrue(len(g2.get_global_rib('10.10.10.0/24')) == 0)
for d in g2.get_global_rib():
for p in d['paths']:
- self.assertFalse(p['stale'])
+ self.assertFalse(p.get('stale', False))
def test_04_add_non_graceful_restart_enabled_peer(self):
g1 = self.bgpds['g1']
diff --git a/test/scenario_test/monitor_test.py b/test/scenario_test/monitor_test.py
index 147391d1..4c5df7c1 100644
--- a/test/scenario_test/monitor_test.py
+++ b/test/scenario_test/monitor_test.py
@@ -87,7 +87,7 @@ class GoBGPTestBase(unittest.TestCase):
while True:
info = qu.get(timeout=120)
print 'monitor got {0}'.format(info)
- self.assertTrue(info['isWithdraw'])
+ self.assertTrue(info['withdrawal'])
break