diff options
author | ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp> | 2015-08-17 15:54:07 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-08-19 13:29:33 +0900 |
commit | c14a63575c62addaf96c78f4de9aef6e3c430f0f (patch) | |
tree | 272698e91435a7cd0a765dee37069096f4052501 | |
parent | 22b43f7ae7daf381520a529157be4c71c11c2bc8 (diff) |
table: withdraw self-generated vrfed routes when a vrf deleted
Signed-off-by: ISHIDA Wataru <ishida.wataru@lab.ntt.co.jp>
-rw-r--r-- | packet/bgp.go | 21 | ||||
-rw-r--r-- | server/server.go | 48 | ||||
-rw-r--r-- | table/table.go | 25 | ||||
-rw-r--r-- | table/table_manager.go | 42 |
4 files changed, 103 insertions, 33 deletions
diff --git a/packet/bgp.go b/packet/bgp.go index a38f4bca..c910f310 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -1395,6 +1395,10 @@ func (er *EVPNEthernetAutoDiscoveryRoute) String() string { return fmt.Sprintf("[type:A-D][rd:%s][esi:%s][etag:%d][label:%d]", er.RD, er.ESI, er.ETag, er.Label) } +func (er *EVPNEthernetAutoDiscoveryRoute) rd() RouteDistinguisherInterface { + return er.RD +} + type EVPNMacIPAdvertisementRoute struct { RD RouteDistinguisherInterface ESI EthernetSegmentIdentifier @@ -1487,6 +1491,10 @@ func (er *EVPNMacIPAdvertisementRoute) String() string { return fmt.Sprintf("[type:macadv][rd:%s][esi:%s][etag:%d][mac:%s][ip:%s][labels:%v]", er.RD, er.ESI.String(), er.ETag, er.MacAddress, er.IPAddress, er.Labels) } +func (er *EVPNMacIPAdvertisementRoute) rd() RouteDistinguisherInterface { + return er.RD +} + type EVPNMulticastEthernetTagRoute struct { RD RouteDistinguisherInterface ETag uint32 @@ -1541,6 +1549,10 @@ func (er *EVPNMulticastEthernetTagRoute) String() string { return fmt.Sprintf("[type:multicast][rd:%s][etag:%d][ip:%s]", er.RD, er.ETag, er.IPAddress) } +func (er *EVPNMulticastEthernetTagRoute) rd() RouteDistinguisherInterface { + return er.RD +} + type EVPNEthernetSegmentRoute struct { RD RouteDistinguisherInterface ESI EthernetSegmentIdentifier @@ -1595,12 +1607,17 @@ type EVPNRouteTypeInterface interface { DecodeFromBytes([]byte) error Serialize() ([]byte, error) String() string + rd() RouteDistinguisherInterface } func (er *EVPNEthernetSegmentRoute) String() string { return fmt.Sprintf("[type:esi][rd:%s][esi:%d][ip:%s]", er.RD, er.ESI, er.IPAddress) } +func (er *EVPNEthernetSegmentRoute) rd() RouteDistinguisherInterface { + return er.RD +} + func getEVPNRouteType(t uint8) (EVPNRouteTypeInterface, error) { switch t { case EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY: @@ -1686,6 +1703,10 @@ func (n *EVPNNLRI) MarshalJSON() ([]byte, error) { }) } +func (n *EVPNNLRI) RD() RouteDistinguisherInterface { + return n.RouteTypeData.rd() +} + func NewEVPNNLRI(routetype uint8, length uint8, routetypedata EVPNRouteTypeInterface) *EVPNNLRI { return &EVPNNLRI{ routetype, diff --git a/server/server.go b/server/server.go index 11fd807a..db1ce6d7 100644 --- a/server/server.go +++ b/server/server.go @@ -967,13 +967,11 @@ ERR: } -func (server *BgpServer) handleVrfMod(arg *api.ModVrfArguments) error { - vrfs := server.localRibMap[GLOBAL_RIB_NAME].rib.Vrfs +func (server *BgpServer) handleVrfMod(arg *api.ModVrfArguments) ([]*table.Path, error) { + manager := server.localRibMap[GLOBAL_RIB_NAME].rib + var msgs []*table.Path switch arg.Operation { case api.Operation_ADD: - if _, ok := vrfs[arg.Vrf.Name]; ok { - return fmt.Errorf("vrf %s already exists", arg.Vrf.Name) - } rd := bgp.GetRouteDistinguisher(arg.Vrf.Rd) f := func(bufs [][]byte) ([]bgp.ExtendedCommunityInterface, error) { ret := make([]bgp.ExtendedCommunityInterface, 0, len(bufs)) @@ -988,42 +986,26 @@ func (server *BgpServer) handleVrfMod(arg *api.ModVrfArguments) error { } importRt, err := f(arg.Vrf.ImportRt) if err != nil { - return err + return nil, err } exportRt, err := f(arg.Vrf.ImportRt) if err != nil { - return err + return nil, err } - log.WithFields(log.Fields{ - "Topic": "Vrf", - "Key": arg.Vrf.Name, - "Rd": rd, - "ImportRt": importRt, - "ExportRt": exportRt, - }).Debugf("add vrf") - vrfs[arg.Vrf.Name] = &table.Vrf{ - Name: arg.Vrf.Name, - Rd: rd, - ImportRt: importRt, - ExportRt: exportRt, + err = manager.AddVrf(arg.Vrf.Name, rd, importRt, exportRt) + if err != nil { + return nil, err } case api.Operation_DEL: - if _, ok := vrfs[arg.Vrf.Name]; !ok { - return fmt.Errorf("vrf %s not found", arg.Vrf.Name) + var err error + msgs, err = manager.DeleteVrf(arg.Vrf.Name) + if err != nil { + return nil, err } - vrf := vrfs[arg.Vrf.Name] - log.WithFields(log.Fields{ - "Topic": "Vrf", - "Key": vrf.Name, - "Rd": vrf.Rd, - "ImportRt": vrf.ImportRt, - "ExportRt": vrf.ExportRt, - }).Debugf("delete vrf") - delete(vrfs, arg.Vrf.Name) default: - return fmt.Errorf("unknown operation:", arg.Operation) + return nil, fmt.Errorf("unknown operation:", arg.Operation) } - return nil + return msgs, nil } func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path { @@ -1074,7 +1056,7 @@ func (server *BgpServer) handleVrfRequest(req *GrpcRequest) []*table.Path { goto END case REQ_VRF_MOD: arg := req.Data.(*api.ModVrfArguments) - result.ResponseErr = server.handleVrfMod(arg) + msgs, result.ResponseErr = server.handleVrfMod(arg) default: result.ResponseErr = fmt.Errorf("unknown request type:", req.RequestType) } diff --git a/table/table.go b/table/table.go index a5f867d4..3bc5bb3f 100644 --- a/table/table.go +++ b/table/table.go @@ -69,6 +69,31 @@ func (t *Table) DeleteDestByPeer(peerInfo *PeerInfo) []*Destination { return changedDests } +func (t *Table) deletePathsByVrf(vrf *Vrf) []*Path { + pathList := make([]*Path, 0) + for _, dest := range t.destinations { + for _, p := range dest.GetKnownPathList() { + var rd bgp.RouteDistinguisherInterface + nlri := p.GetNlri() + switch nlri.(type) { + case *bgp.LabeledVPNIPAddrPrefix: + rd = nlri.(*bgp.LabeledVPNIPAddrPrefix).RD + case *bgp.LabeledVPNIPv6AddrPrefix: + rd = nlri.(*bgp.LabeledVPNIPv6AddrPrefix).RD + case *bgp.EVPNNLRI: + rd = nlri.(*bgp.EVPNNLRI).RD() + default: + return pathList + } + if p.IsLocal() && vrf.Rd.String() == rd.String() { + p.IsWithdraw = true + pathList = append(pathList, p) + } + } + } + return pathList +} + func (t *Table) deleteDestByNlri(nlri bgp.AddrPrefixInterface) *Destination { destinations := t.GetDestinations() dest := destinations[t.tableKey(nlri)] diff --git a/table/table_manager.go b/table/table_manager.go index 41630246..e44babe7 100644 --- a/table/table_manager.go +++ b/table/table_manager.go @@ -17,6 +17,7 @@ package table import ( "bytes" + "fmt" log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet" "net" @@ -134,6 +135,47 @@ func (manager *TableManager) OwnerName() string { return manager.owner } +func (manager *TableManager) AddVrf(name string, rd bgp.RouteDistinguisherInterface, importRt, exportRt []bgp.ExtendedCommunityInterface) error { + if _, ok := manager.Vrfs[name]; ok { + return fmt.Errorf("vrf %s already exists", name) + } + log.WithFields(log.Fields{ + "Topic": "Vrf", + "Key": name, + "Rd": rd, + "ImportRt": importRt, + "ExportRt": exportRt, + }).Debugf("add vrf") + manager.Vrfs[name] = &Vrf{ + Name: name, + Rd: rd, + ImportRt: importRt, + ExportRt: exportRt, + } + return nil + +} + +func (manager *TableManager) DeleteVrf(name string) ([]*Path, error) { + if _, ok := manager.Vrfs[name]; !ok { + return nil, fmt.Errorf("vrf %s not found", name) + } + msgs := make([]*Path, 0) + vrf := manager.Vrfs[name] + for _, t := range manager.Tables { + msgs = append(msgs, t.deletePathsByVrf(vrf)...) + } + log.WithFields(log.Fields{ + "Topic": "Vrf", + "Key": vrf.Name, + "Rd": vrf.Rd, + "ImportRt": vrf.ImportRt, + "ExportRt": vrf.ExportRt, + }).Debugf("delete vrf") + delete(manager.Vrfs, name) + return msgs, nil +} + func (manager *TableManager) calculate(destinationList []*Destination) ([]*Path, error) { newPaths := make([]*Path, 0) |