Skip to content
This repository has been archived by the owner on Feb 2, 2024. It is now read-only.

wip #26

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

wip #26

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,12 @@ matrix:
services:
- docker
script: test/travis_script.sh
- go: 1.7
sudo: required
env:
- TEST=test/netlink/iptables_test.py
services:
- docker
script: test/travis_script.sh

go_import_path: github.com/osrg/goplane
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ FROM osrg/gobgp

MAINTAINER ISHIDA Wataru <[email protected]>

RUN apt-get install -qy iptables
ENV GO15VENDOREXPERIMENT 1
RUN curl https://glide.sh/get | sh
ADD . $GOPATH/src/github.com/osrg/goplane/
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type Iptables struct {
}

type Config struct {
RouterID string `mapstructure:"router-id"`
Dataplane Dataplane `mapstructure:"dataplane"`
Iptables Iptables `mapstructure:"iptables"`
BGP bgpconfig.BgpConfigSet `mapstructure:"bgp"`
Expand Down
127 changes: 127 additions & 0 deletions dataplane.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (C) 2017 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 main

import (
"fmt"
"net"
"sync"

log "github.com/Sirupsen/logrus"
"github.com/osrg/goplane/config"
proto "github.com/osrg/goplane/protocol"
)

type Dataplane struct {
routerID net.IP
protos map[proto.ProtocolType]proto.Protocol
routeEventCh chan []proto.EntryEvent
m sync.RWMutex
}

func NewDataplane() *Dataplane {
d := &Dataplane{
protos: make(map[proto.ProtocolType]proto.Protocol),
routeEventCh: make(chan []proto.EntryEvent, 0),
}
go func() {
log.Fatal(d.serve())
}()
return d
}

func (d *Dataplane) serve() error {
for {
for _, ev := range <-d.routeEventCh {
log.Info("ev:", ev)
d.m.RLock()
for _, proto := range d.protos {
if ev.From == proto.Type() || ev.Entry.Match() == nil {
continue
}
var err error
if ev.IsDel {
err = proto.DeleteEntry(ev.Entry)
} else {
err = proto.AddEntry(ev.Entry)
}
if err != nil {
log.Errorf("err: %v", err)
}
}
d.m.RUnlock()
}
}
return nil
}

func (d *Dataplane) SetRouterID(id net.IP) error {
d.m.RLock()
defer d.m.RUnlock()
for _, proto := range d.protos {
if err := proto.SetRouterID(id); err != nil {
return err
}
}
return nil
}

func (d *Dataplane) AddProtocol(p proto.Protocol) error {
d.m.Lock()
defer d.m.Unlock()
if _, y := d.protos[p.Type()]; y {
return fmt.Errorf("protocol %d already exists", p.Type())
}
d.protos[p.Type()] = p
w, err := p.WatchEntry()
if err != nil {
return err
}
if w != nil {
go func() {
for {
rs, err := w.Recv()
if err != nil {
log.Fatalf("failed recv routes: %s", err)
}
d.routeEventCh <- rs
}
}()
}
return nil
}

func (d *Dataplane) AddVirtualNetwork(c config.VirtualNetwork) error {
d.m.RLock()
defer d.m.RUnlock()
for _, proto := range d.protos {
if err := proto.AddVirtualNetwork(d.routerID.String(), c); err != nil {
return err
}
}
return nil
}

func (d *Dataplane) DeleteVirtualNetwork(c config.VirtualNetwork) error {
d.m.RLock()
defer d.m.RUnlock()
for _, proto := range d.protos {
if err := proto.DeleteVirtualNetwork(c); err != nil {
return err
}
}
return nil
}
139 changes: 23 additions & 116 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ package main
import (
"io/ioutil"
"log/syslog"
"net"
"os"
"os/signal"
"runtime"
"strings"
"syscall"
"time"

log "github.com/Sirupsen/logrus"
"github.com/Sirupsen/logrus/hooks/syslog"
"github.com/jessevdk/go-flags"
"github.com/osrg/goplane/config"
"github.com/osrg/goplane/iptables"
"github.com/osrg/goplane/netlink"
p "github.com/osrg/goplane/protocol"
"github.com/osrg/goplane/protocol/iptables"
"github.com/osrg/goplane/protocol/netlink"

bgpapi "github.com/osrg/gobgp/api"
bgpconfig "github.com/osrg/gobgp/config"
"github.com/osrg/gobgp/packet/bgp"
bgpserver "github.com/osrg/gobgp/server"
)

type Dataplaner interface {
Expand Down Expand Up @@ -157,127 +157,44 @@ func main() {
go config.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh, bgpConfigCh, reloadCh)
reloadCh <- true

var bgpServer *bgpserver.BgpServer
if !opts.Remote {
bgpServer = bgpserver.NewBgpServer()
go bgpServer.Serve()
grpcServer := bgpapi.NewGrpcServer(bgpServer, opts.GrpcHost)
go func() {
if err := grpcServer.Serve(); err != nil {
log.Fatalf("failed to listen grpc port: %s", err)
}
}()
}
bgpProtocol := p.NewGoBGPProtocol()
dataplane := NewDataplane()
dataplane.AddProtocol(bgpProtocol)

var dataplane Dataplaner
var d *config.Dataplane
var c *bgpconfig.BgpConfigSet
var fsAgent *iptables.FlowspecAgent
for {
select {
case newConfig := <-bgpConfigCh:
if opts.Remote {
log.Warn("running in BGP remote mode. you can't configure BGP daemon via configuration file now")
continue
}

var added, deleted, updated []bgpconfig.Neighbor
var updatePolicy bool

if c == nil {
c = newConfig
if err := bgpServer.Start(&newConfig.Global); err != nil {
log.Fatalf("failed to set global config: %s", err)
}
if newConfig.Zebra.Config.Enabled {
if err := bgpServer.StartZebraClient(&newConfig.Zebra.Config); err != nil {
log.Fatalf("failed to set zebra config: %s", err)
}
}
if len(newConfig.Collector.Config.Url) > 0 {
if err := bgpServer.StartCollector(&newConfig.Collector.Config); err != nil {
log.Fatalf("failed to set collector config: %s", err)
}
}
for _, c := range newConfig.RpkiServers {
if err := bgpServer.AddRpki(&c.Config); err != nil {
log.Fatalf("failed to set rpki config: %s", err)
}
}
for _, c := range newConfig.BmpServers {
if err := bgpServer.AddBmp(&c.Config); err != nil {
log.Fatalf("failed to set bmp config: %s", err)
}
}
for _, c := range newConfig.MrtDump {
if len(c.Config.FileName) == 0 {
continue
}
if err := bgpServer.EnableMrt(&c.Config); err != nil {
log.Fatalf("failed to set mrt config: %s", err)
}
}
p := bgpconfig.ConfigSetToRoutingPolicy(newConfig)
if err := bgpServer.UpdatePolicy(*p); err != nil {
log.Fatalf("failed to set routing policy: %s", err)
}

added = newConfig.Neighbors
if opts.GracefulRestart {
for i, n := range added {
if n.GracefulRestart.Config.Enabled {
added[i].GracefulRestart.State.LocalRestarting = true
}
}
}

} else {
added, deleted, updated, updatePolicy = bgpconfig.UpdateConfig(c, newConfig)
if updatePolicy {
log.Info("Policy config is updated")
p := bgpconfig.ConfigSetToRoutingPolicy(newConfig)
bgpServer.UpdatePolicy(*p)
}
c = newConfig
if err := bgpProtocol.UpdateConfig(newConfig); err != nil {
log.Fatalf("failed to update BGP config: %s", err)
}

for i, p := range added {
log.Infof("Peer %v is added", p.Config.NeighborAddress)
bgpServer.AddNeighbor(&added[i])
}
for i, p := range deleted {
log.Infof("Peer %v is deleted", p.Config.NeighborAddress)
bgpServer.DeleteNeighbor(&deleted[i])
}
for i, p := range updated {
log.Infof("Peer %v is updated", p.Config.NeighborAddress)
u, _ := bgpServer.UpdateNeighbor(&updated[i])
updatePolicy = updatePolicy || u
}

if updatePolicy {
bgpServer.SoftResetIn("", bgp.RouteFamily(0))
}

case newConfig := <-configCh:
if dataplane == nil {
if d == nil {
switch newConfig.Dataplane.Type {
case "netlink":
log.Debug("new dataplane: netlink")
dataplane = netlink.NewDataplane(newConfig, opts.GrpcHost)
go func() {
err := dataplane.Serve()
if err != nil {
log.Errorf("dataplane finished with err: %s", err)
}
}()
dataplane.AddProtocol(netlink.NewNetlinkProtocol())
default:
log.Errorf("Invalid dataplane type(%s). dataplane engine can't be started", newConfig.Dataplane.Type)
}

time.Sleep(time.Millisecond)

if err := dataplane.SetRouterID(net.ParseIP(newConfig.RouterID)); err != nil {
log.Fatal(err)
}

if newConfig.Iptables.Enabled {
dataplane.AddProtocol(iptables.NewIPTablesProtocol(newConfig.Iptables))
}
}
d = &newConfig.Dataplane

as, ds := config.UpdateConfig(d, newConfig.Dataplane)
d = &newConfig.Dataplane

for _, v := range as {
log.Infof("VirtualNetwork %s is added", v.RD)
Expand All @@ -288,16 +205,6 @@ func main() {
dataplane.DeleteVirtualNetwork(v)
}

if fsAgent == nil && newConfig.Iptables.Enabled {
fsAgent = iptables.NewFlowspecAgent(opts.GrpcHost, newConfig.Iptables)
go func() {
err := fsAgent.Serve()
if err != nil {
log.Errorf("flowspec agent finished with err: %s", err)
}
}()
}

case sig := <-sigCh:
switch sig {
case syscall.SIGHUP:
Expand Down
Loading