summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-08-12 13:16:58 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2015-08-12 13:44:33 +0900
commit6180ffb7106e3673e4da5a2d2ce1f87612462721 (patch)
tree74646c52142ccda5b34231207cc741f8288f38ec
parentc2f5b1a176a1b7f72658821d057e23414e839718 (diff)
support rpki validation
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--api/gobgp.pb.go1
-rw-r--r--api/gobgp.proto1
-rw-r--r--gobgp/common.go2
-rw-r--r--gobgp/neighbor.go17
-rw-r--r--gobgp/rpki.go23
-rw-r--r--server/rpki.go62
-rw-r--r--server/server.go4
-rw-r--r--table/path.go6
8 files changed, 88 insertions, 28 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go
index 4d91e526..9eebd786 100644
--- a/api/gobgp.pb.go
+++ b/api/gobgp.pb.go
@@ -322,6 +322,7 @@ type Path struct {
Age int64 `protobuf:"varint,3,opt,name=age" json:"age,omitempty"`
Best bool `protobuf:"varint,4,opt,name=best" json:"best,omitempty"`
IsWithdraw bool `protobuf:"varint,5,opt,name=is_withdraw" json:"is_withdraw,omitempty"`
+ Validation int32 `protobuf:"varint,6,opt,name=validation" json:"validation,omitempty"`
}
func (m *Path) Reset() { *m = Path{} }
diff --git a/api/gobgp.proto b/api/gobgp.proto
index 650e452b..5c5afbfe 100644
--- a/api/gobgp.proto
+++ b/api/gobgp.proto
@@ -144,6 +144,7 @@ message Path {
int64 age = 3;
bool best = 4;
bool is_withdraw = 5;
+ int32 validation = 6;
}
message Destination {
diff --git a/gobgp/common.go b/gobgp/common.go
index 31e0802a..12c08256 100644
--- a/gobgp/common.go
+++ b/gobgp/common.go
@@ -152,6 +152,7 @@ type Path struct {
Age int64 `json:"age"`
Best bool `json:"best"`
IsWithdraw bool `json:"isWithdraw"`
+ Validation int32
}
func ApiStruct2Path(p *api.Path) (*Path, error) {
@@ -192,6 +193,7 @@ func ApiStruct2Path(p *api.Path) (*Path, error) {
Age: p.Age,
Best: p.Best,
IsWithdraw: p.IsWithdraw,
+ Validation: p.Validation,
}, nil
}
diff --git a/gobgp/neighbor.go b/gobgp/neighbor.go
index ad700311..4b3b8425 100644
--- a/gobgp/neighbor.go
+++ b/gobgp/neighbor.go
@@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"github.com/osrg/gobgp/api"
+ "github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet"
"github.com/osrg/gobgp/policy"
"github.com/spf13/cobra"
@@ -305,11 +306,19 @@ func showRoute(pathList []*Path, showAge bool, showBest bool, isMonitor bool) {
}
best := ""
+ switch config.RpkiValidationResultType(p.Validation) {
+ case config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND:
+ best += "N"
+ case config.RPKI_VALIDATION_RESULT_TYPE_VALID:
+ best += "V"
+ case config.RPKI_VALIDATION_RESULT_TYPE_INVALID:
+ best += "I"
+ }
if showBest {
if p.Best {
- best = "*>"
+ best += "*>"
} else {
- best = "* "
+ best += "* "
}
}
@@ -334,10 +343,10 @@ func showRoute(pathList []*Path, showAge bool, showBest bool, isMonitor bool) {
if isMonitor {
format = "[%s] %s via %s aspath [%s] attrs %s\n"
} else if showAge {
- format = fmt.Sprintf("%%-2s %%-%ds %%-%ds %%-%ds %%-10s %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
+ format = fmt.Sprintf("%%-3s %%-%ds %%-%ds %%-%ds %%-10s %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Age", "Attrs")
} else {
- format = fmt.Sprintf("%%-2s %%-%ds %%-%ds %%-%ds %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
+ format = fmt.Sprintf("%%-3s %%-%ds %%-%ds %%-%ds %%-s\n", maxPrefixLen, maxNexthopLen, maxAsPathLen)
fmt.Printf(format, "", "Network", "Next Hop", "AS_PATH", "Attrs")
}
diff --git a/gobgp/rpki.go b/gobgp/rpki.go
index 2d0a3577..89632eac 100644
--- a/gobgp/rpki.go
+++ b/gobgp/rpki.go
@@ -24,7 +24,6 @@ import (
"io"
"net"
"os"
- "sort"
)
func showRPKITable(args []string) error {
@@ -41,17 +40,7 @@ func showRPKITable(args []string) error {
fmt.Println(err)
return err
}
- l := roas{}
- for {
- r, err := stream.Recv()
- if err == io.EOF {
- break
- } else if err != nil {
- return err
- }
- l = append(l, r)
- }
- sort.Sort(l)
+
var format string
afi, _ := bgp.RouteFamilyToAfiSafi(rf)
if afi == bgp.AFI_IP {
@@ -60,8 +49,14 @@ func showRPKITable(args []string) error {
format = "%-42s %-6s %s\n"
}
fmt.Printf(format, "Network", "Maxlen", "AS")
- for _, r := range l {
- fmt.Printf(format, fmt.Sprintf("%s/%d", r.Prefix, r.Prefixlen), fmt.Sprint(r.Maxlen), fmt.Sprint(r.Maxlen))
+ for {
+ r, err := stream.Recv()
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ return err
+ }
+ fmt.Printf(format, fmt.Sprintf("%s/%d", r.Prefix, r.Prefixlen), fmt.Sprint(r.Maxlen), fmt.Sprint(r.As))
}
return nil
}
diff --git a/server/rpki.go b/server/rpki.go
index 6ad6aa0a..1261b7c8 100644
--- a/server/rpki.go
+++ b/server/rpki.go
@@ -17,9 +17,13 @@ package server
import (
"bufio"
+ "bytes"
"fmt"
+ "github.com/armon/go-radix"
"github.com/osrg/gobgp/api"
+ "github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet"
+ "github.com/osrg/gobgp/table"
"net"
)
@@ -44,7 +48,8 @@ func (r *roa) toApiStruct() *api.ROA {
}
type roaClient struct {
- roas map[bgp.RouteFamily]map[string]*roa
+ url string
+ roas map[bgp.RouteFamily]*radix.Tree
outgoing chan *roa
}
@@ -52,31 +57,70 @@ func (c *roaClient) recieveROA() chan *roa {
return c.outgoing
}
+func roa2key(r *roa) string {
+ var buffer bytes.Buffer
+ for i := 0; i < len(r.Prefix) && i < int(r.PrefixLen); i++ {
+ buffer.WriteString(fmt.Sprintf("%08b", r.Prefix[i]))
+ }
+ return buffer.String()[:r.PrefixLen]
+}
+
func (c *roaClient) handleRTRMsg(r *roa) {
if r.Prefix.To4() != nil {
- c.roas[bgp.RF_IPv4_UC][r.key()] = r
+ c.roas[bgp.RF_IPv4_UC].Insert(roa2key(r), r)
} else {
- c.roas[bgp.RF_IPv6_UC][r.key()] = r
+ c.roas[bgp.RF_IPv6_UC].Insert(roa2key(r), r)
}
}
func (c *roaClient) handleGRPC(grpcReq *GrpcRequest) {
- if roas, ok := c.roas[grpcReq.RouteFamily]; ok {
- for _, r := range roas {
+ if tree, ok := c.roas[grpcReq.RouteFamily]; ok {
+ tree.Walk(func(s string, v interface{}) bool {
+ r, _ := v.(*roa)
result := &GrpcResponse{}
result.Data = r.toApiStruct()
grpcReq.ResponseCh <- result
- }
+ return false
+ })
}
close(grpcReq.ResponseCh)
}
+func (c *roaClient) validate(pathList []*table.Path) {
+ if c.url == "" {
+ return
+ }
+
+ for _, path := range pathList {
+ if tree, ok := c.roas[path.GetRouteFamily()]; ok {
+ _, n, _ := net.ParseCIDR(path.GetNlri().String())
+ ones, _ := n.Mask.Size()
+ var buffer bytes.Buffer
+ for i := 0; i < len(n.IP) && i < ones; i++ {
+ buffer.WriteString(fmt.Sprintf("%08b", n.IP[i]))
+ }
+ _, r, _ := tree.LongestPrefix(buffer.String()[:ones])
+ if r == nil {
+ path.Validation = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND
+ } else {
+ roa, _ := r.(*roa)
+ if roa.AS == path.GetSourceAs() {
+ path.Validation = config.RPKI_VALIDATION_RESULT_TYPE_VALID
+ } else {
+ path.Validation = config.RPKI_VALIDATION_RESULT_TYPE_INVALID
+ }
+ }
+ }
+ }
+}
+
func newROAClient(url string) (*roaClient, error) {
c := &roaClient{
- roas: make(map[bgp.RouteFamily]map[string]*roa),
+ url: url,
+ roas: make(map[bgp.RouteFamily]*radix.Tree),
}
- c.roas[bgp.RF_IPv4_UC] = make(map[string]*roa)
- c.roas[bgp.RF_IPv6_UC] = make(map[string]*roa)
+ c.roas[bgp.RF_IPv4_UC] = radix.New()
+ c.roas[bgp.RF_IPv6_UC] = radix.New()
if url == "" {
return c, nil
diff --git a/server/server.go b/server/server.go
index b1d0d956..4c202209 100644
--- a/server/server.go
+++ b/server/server.go
@@ -683,6 +683,10 @@ func (server *BgpServer) handleFSMMessage(peer *Peer, e *fsmMsg, incoming chan *
msgs = append(msgs, newSenderMsg(peer, msgList))
}
break
+ } else {
+ if len(pathList) > 0 {
+ server.roaClient.validate(pathList)
+ }
}
msgs = append(msgs, server.propagateUpdate(peer.conf.NeighborConfig.NeighborAddress.String(),
peer.isRouteServerClient(), pathList)...)
diff --git a/table/path.go b/table/path.go
index b3a84d9d..8025a63a 100644
--- a/table/path.go
+++ b/table/path.go
@@ -36,6 +36,7 @@ type Path struct {
medSetByTargetNeighbor bool
timestamp time.Time
NoImplicitWithdraw bool
+ Validation config.RpkiValidationResultType
}
func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, medSetByTargetNeighbor bool, timestamp time.Time, noImplicitWithdraw bool) *Path {
@@ -156,6 +157,7 @@ func (path *Path) ToApiStruct() *api.Path {
Pattrs: pattrs,
Age: int64(time.Now().Sub(path.timestamp).Seconds()),
IsWithdraw: path.IsWithdraw,
+ Validation: int32(path.Validation),
}
}
@@ -189,7 +191,9 @@ func (path *Path) Clone(isWithdraw bool) *Path {
newPathAttrs[i] = v
}
- return NewPath(path.source, nlri, isWithdraw, newPathAttrs, false, path.timestamp, path.NoImplicitWithdraw)
+ p := NewPath(path.source, nlri, isWithdraw, newPathAttrs, false, path.timestamp, path.NoImplicitWithdraw)
+ p.Validation = path.Validation
+ return p
}
func (path *Path) GetRouteFamily() bgp.RouteFamily {