Exemple #1
0
func (m *OpsManager) handleBgpRouterUpdate(update ovsdb.TableUpdate) []*server.GrpcRequest {
	asn, id, err := m.getBGPRouterUUID()
	if err != nil {
		log.Debugf("%s", err)
		return nil
	}
	reqs := []*server.GrpcRequest{}
	for k, v := range update.Rows {
		if uuid.Equal(id, uuid.FromStringOrNil(k)) {
			initial := false
			if len(v.Old.Fields) == 0 {
				log.WithFields(log.Fields{
					"Topic": "openswitch",
				}).Debug("new bgp router")
				initial = true
			}
			if _, ok := v.Old.Fields["router_id"]; initial || ok {
				r, ok := v.New.Fields["router_id"].(string)
				if !ok {
					log.WithFields(log.Fields{
						"Topic": "openswitch",
					}).Debug("router-id is not configured yet")
					return nil
				}
				reqs = append(reqs, server.NewGrpcRequest(server.REQ_START_SERVER, "", bgp.RouteFamily(0), &api.StartServerRequest{
					Global: &api.Global{
						As:       asn,
						RouterId: r,
					},
				}))
			}
			if o, ok := v.Old.Fields["bgp_neighbors"]; ok {
				oldNeighMap := o.(ovsdb.OvsMap).GoMap
				newNeighMap := v.New.Fields["bgp_neighbors"].(ovsdb.OvsMap).GoMap
				for k, _ := range oldNeighMap {
					if _, ok := newNeighMap[k]; !ok {
						reqs = append(reqs, server.NewGrpcRequest(server.REQ_GRPC_DELETE_NEIGHBOR, "", bgp.RouteFamily(0), &api.DeleteNeighborRequest{
							Peer: &api.Peer{
								Conf: &api.PeerConf{
									NeighborAddress: k.(string),
								},
							},
						}))
					}
				}
			}
		}
	}
	return reqs
}
Exemple #2
0
func (s *Server) InjectMrt(stream api.GobgpApi_InjectMrtServer) error {
	for {
		arg, err := stream.Recv()

		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		if arg.Resource != api.Resource_GLOBAL && arg.Resource != api.Resource_VRF {
			return fmt.Errorf("unsupported resource: %s", arg.Resource)
		}

		req := NewGrpcRequest(REQ_INJECT_MRT, "", bgp.RouteFamily(0), arg)
		s.bgpServerCh <- req

		res := <-req.ResponseCh
		if err := res.Err(); err != nil {
			log.Debug(err.Error())
			return err
		}
	}
	return stream.SendAndClose(&api.InjectMrtResponse{})
}
Exemple #3
0
func (m *OpsManager) handleNeighborUpdate(update ovsdb.TableUpdate) []*server.GrpcRequest {
	_, id, _ := m.getBGPRouterUUID()
	addrs, ids, err := m.getBGPNeighborUUIDs(id)
	if err != nil {
		return nil
	}
	reqs := make([]*server.GrpcRequest, 0, len(addrs))
	for k, v := range update.Rows {
		for idx, id := range ids {
			if uuid.Equal(id, uuid.FromStringOrNil(k)) {
				asn, ok := v.New.Fields["remote_as"].(float64)
				if !ok {
					log.WithFields(log.Fields{
						"Topic": "openswitch",
					}).Debug("remote-as is not configured yet")
					continue
				}
				reqs = append(reqs, server.NewGrpcRequest(server.REQ_GRPC_ADD_NEIGHBOR, "", bgp.RouteFamily(0), &api.AddNeighborRequest{
					Peer: &api.Peer{
						Conf: &api.PeerConf{
							NeighborAddress: addrs[idx].String(),
							PeerAs:          uint32(asn),
						},
					},
				}))
			}
		}
	}
	return reqs
}
Exemple #4
0
func (s *Server) StartServer(ctx context.Context, arg *StartServerRequest) (*StartServerResponse, error) {
	g := arg.Global
	if net.ParseIP(g.RouterId) == nil {
		return nil, fmt.Errorf("invalid router-id format: %s", g.RouterId)
	}
	families := make([]config.AfiSafi, 0, len(g.Families))
	for _, f := range g.Families {
		name := config.AfiSafiType(bgp.RouteFamily(f).String())
		families = append(families, config.AfiSafi{
			Config: config.AfiSafiConfig{
				AfiSafiName: name,
				Enabled:     true,
			},
			State: config.AfiSafiState{
				AfiSafiName: name,
			},
		})
	}
	b := &config.BgpConfigSet{
		Global: config.Global{
			Config: config.GlobalConfig{
				As:               g.As,
				RouterId:         g.RouterId,
				Port:             g.ListenPort,
				LocalAddressList: g.ListenAddresses,
			},
			MplsLabelRange: config.MplsLabelRange{
				MinLabel: g.MplsLabelMin,
				MaxLabel: g.MplsLabelMax,
			},
			AfiSafis: families,
		},
	}
	return &StartServerResponse{}, s.bgpServer.Start(&b.Global)
}
Exemple #5
0
func showRPKITable(args []string) error {
	family, err := checkAddressFamily(bgp.RouteFamily(0))
	if err != nil {
		exitWithError(err)
	}
	arg := &api.GetRoaRequest{
		Family: uint32(family),
	}
	rsp, err := client.GetRoa(context.Background(), arg)
	if err != nil {
		fmt.Println(err)
		return err
	}

	var format string
	afi, _ := bgp.RouteFamilyToAfiSafi(family)
	if afi == bgp.AFI_IP {
		format = "%-18s %-6s %-10s %s\n"
	} else {
		format = "%-42s %-6s %-10s %s\n"
	}
	fmt.Printf(format, "Network", "Maxlen", "AS", "Server")
	for _, r := range rsp.Roas {
		if len(args) > 0 && args[0] != r.Conf.Address {
			continue
		}

		server := net.JoinHostPort(r.Conf.Address, r.Conf.RemotePort)
		fmt.Printf(format, fmt.Sprintf("%s/%d", r.Prefix, r.Prefixlen), fmt.Sprint(r.Maxlen), fmt.Sprint(r.As), server)
	}
	return nil
}
Exemple #6
0
func showRPKITable(args []string) error {
	family, err := checkAddressFamily(bgp.RouteFamily(0))
	if err != nil {
		exitWithError(err)
	}
	roas, err := client.GetROA(family)
	if err != nil {
		exitWithError(err)
	}

	var format string
	afi, _ := bgp.RouteFamilyToAfiSafi(family)
	if afi == bgp.AFI_IP {
		format = "%-18s %-6s %-10s %s\n"
	} else {
		format = "%-42s %-6s %-10s %s\n"
	}
	fmt.Printf(format, "Network", "Maxlen", "AS", "Server")
	for _, r := range roas {
		host, _, _ := net.SplitHostPort(r.Src)
		if len(args) > 0 && args[0] != host {
			continue
		}
		fmt.Printf(format, r.Prefix.String(), fmt.Sprint(r.MaxLen), fmt.Sprint(r.AS), r.Src)
	}
	return nil
}
Exemple #7
0
func addr2AddressFamily(a net.IP) bgp.RouteFamily {
	if a.To4() != nil {
		return bgp.RF_IPv4_UC
	} else if a.To16() != nil {
		return bgp.RF_IPv6_UC
	}
	return bgp.RouteFamily(0)
}
Exemple #8
0
func (s *Server) GetVrf(ctx context.Context, arg *api.GetVrfRequest) (*api.GetVrfResponse, error) {
	req := NewGrpcRequest(REQ_GET_VRF, "", bgp.RouteFamily(0), nil)
	s.bgpServerCh <- req
	res := <-req.ResponseCh
	if res.Err() != nil {
		return nil, res.Err()
	}
	return res.Data.(*api.GetVrfResponse), res.Err()
}
Exemple #9
0
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
}
Exemple #10
0
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
}
Exemple #11
0
func (s *Server) DeletePath(ctx context.Context, arg *DeletePathRequest) (*DeletePathResponse, error) {
	pathList, err := func() ([]*table.Path, error) {
		if arg.Path != nil {
			arg.Path.IsWithdraw = true
			return s.api2PathList(arg.Resource, []*Path{arg.Path})
		}
		return []*table.Path{}, nil
	}()
	if err != nil {
		return nil, err
	}
	return &DeletePathResponse{}, s.bgpServer.DeletePath(arg.Uuid, bgp.RouteFamily(arg.Family), arg.VrfId, pathList)
}
Exemple #12
0
func (s *Server) MonitorRib(arg *api.Table, stream api.GobgpApi_MonitorRibServer) error {
	switch arg.Type {
	case api.Resource_ADJ_IN, api.Resource_GLOBAL:
	default:
		return fmt.Errorf("unsupported resource type: %v", arg.Type)
	}

	req := NewGrpcRequest(REQ_MONITOR_RIB, arg.Name, bgp.RouteFamily(arg.Family), arg)
	s.bgpServerCh <- req
	return handleMultipleResponses(req, func(res *GrpcResponse) error {
		return stream.Send(res.Data.(*api.Destination))
	})
}
Exemple #13
0
func resetNeighbor(cmd string, remoteIP string, args []string) error {
	family := bgp.RouteFamily(0)
	switch cmd {
	case CMD_RESET:
		return client.ResetNeighbor(remoteIP)
	case CMD_SOFT_RESET:
		return client.SoftReset(remoteIP, family)
	case CMD_SOFT_RESET_IN:
		return client.SoftResetIn(remoteIP, family)
	case CMD_SOFT_RESET_OUT:
		return client.SoftResetOut(remoteIP, family)
	}
	return nil
}
Exemple #14
0
func (m *OpsManager) handleRouteUpdate(update ovsdb.TableUpdate) []*server.GrpcRequest {
	id, _ := m.getVrfUUID()
	reqs := []*server.GrpcRequest{}
	for _, v := range update.Rows {
		vrf := v.New.Fields["vrf"]
		if vrf == nil {
			continue
		}
		idx := vrf.(ovsdb.UUID).GoUUID
		if uuid.Equal(id, uuid.FromStringOrNil(idx)) {
			path, isWithdraw, isFromGobgp, err := parseRouteToGobgp(v, m.cache["BGP_Nexthop"])
			if err != nil {
				log.WithFields(log.Fields{
					"Topic": "openswitch",
					"Path":  path,
					"Err":   err,
				}).Debug("failed to parse path")
				return nil
			}
			if isWithdraw {
				reqs = append(reqs, server.NewGrpcRequest(server.REQ_DELETE_PATH, "", bgp.RouteFamily(0), &api.AddPathRequest{
					Resource: api.Resource_GLOBAL,
					Path:     path,
				}))
			} else {
				if isFromGobgp {
					return nil
				}
				reqs = append(reqs, server.NewGrpcRequest(server.REQ_ADD_PATH, "", bgp.RouteFamily(0), &api.AddPathRequest{
					Resource: api.Resource_GLOBAL,
					Path:     path,
				}))
			}
		}
	}
	return reqs
}
Exemple #15
0
func (m *OpsManager) handleVrfUpdate(update ovsdb.TableUpdate) *server.GrpcRequest {
	for _, v := range update.Rows {
		if len(v.Old.Fields) == 0 {
			log.WithFields(log.Fields{
				"Topic": "openswitch",
			}).Debug("new vrf")
		} else if _, ok := v.Old.Fields["bgp_routers"]; ok {
			_, _, err := m.getBGPRouterUUID()
			if err != nil {
				return server.NewGrpcRequest(server.REQ_STOP_SERVER, "", bgp.RouteFamily(0), &api.StopServerRequest{})
			}
		}
	}
	return nil
}
Exemple #16
0
//export serialize_path
func serialize_path(rf C.int, input *C.char) *C.path {
	args := strings.Split(C.GoString(input), " ")
	p, err := cmd.ParsePath(bgp.RouteFamily(rf), args)
	if err != nil {
		return nil
	}
	path := C.new_path()
	if len(p.Nlri) > 0 {
		path.nlri.len = C.int(len(p.Nlri))
		path.nlri.value = C.CString(string(p.Nlri))
	}
	for _, attr := range p.Pattrs {
		C.append_path_attribute(path, C.int(len(attr)), C.CString(string(attr)))
	}
	return path
}
Exemple #17
0
func (s *Server) MonitorBestChanged(arg *api.Arguments, stream api.GobgpApi_MonitorBestChangedServer) error {
	var reqType int
	switch arg.Resource {
	case api.Resource_GLOBAL:
		reqType = REQ_MONITOR_GLOBAL_BEST_CHANGED
	default:
		return fmt.Errorf("unsupported resource type: %v", arg.Resource)
	}

	req := NewGrpcRequest(reqType, "", bgp.RouteFamily(arg.Family), nil)
	s.bgpServerCh <- req

	return handleMultipleResponses(req, func(res *GrpcResponse) error {
		return stream.Send(res.Data.(*api.Destination))
	})
}
Exemple #18
0
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
}
Exemple #19
0
func (m *OpsManager) GobgpMonitor(ready *bool) {
	time.Sleep(time.Duration(time.Second * 2))
	reqCh := m.grpcCh
	family := bgp.RF_IPv4_UC
	arg := &api.Arguments{
		Resource: api.Resource_GLOBAL,
		Family:   uint32(family),
	}
	for {
		if !*ready {
			return
		}
		req := server.NewGrpcRequest(server.REQ_MONITOR_GLOBAL_BEST_CHANGED, "", bgp.RouteFamily(0), arg)
		reqCh <- req
		res := <-req.ResponseCh
		if err := res.Err(); err != nil {
			log.WithFields(log.Fields{
				"Topic":       "openswitch",
				"Type":        "Monitor",
				"RequestType": req.RequestType,
				"Err":         err,
			}).Error("grpc operation failed")
		}
		d := res.Data.(*api.Destination)
		bPath := d.Paths[0]
		if bPath.IsFromExternal && !bPath.IsWithdraw {
			continue
		}
		p, err := cmd.ApiStruct2Path(bPath)
		if err != nil {
			log.WithFields(log.Fields{
				"Topic": "openswitch",
				"Type":  "MonitorRequest",
				"Err":   err,
			}).Error("failed parse path of gobgp")
		}
		o, err := m.TransactPreparation(p)
		if err != nil {
			log.WithFields(log.Fields{
				"Topic": "openswitch",
				"Type":  "Monitor",
				"Err":   err,
			}).Error("failed transact preparation of ops")
		}
		m.opsCh <- o
	}
}
Exemple #20
0
func (s *Server) SoftResetNeighbor(ctx context.Context, arg *SoftResetNeighborRequest) (*SoftResetNeighborResponse, error) {
	var err error
	addr := arg.Address
	if addr == "all" {
		addr = ""
	}
	family := bgp.RouteFamily(0)
	switch arg.Direction {
	case SoftResetNeighborRequest_IN:
		err = s.bgpServer.SoftResetIn(addr, family)
	case SoftResetNeighborRequest_OUT:
		err = s.bgpServer.SoftResetOut(addr, family)
	default:
		err = s.bgpServer.SoftReset(addr, family)
	}
	return &SoftResetNeighborResponse{}, err
}
Exemple #21
0
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
}
Exemple #22
0
func (s *Server) GetRoa(ctx context.Context, arg *GetRoaRequest) (*GetRoaResponse, error) {
	roas, err := s.bgpServer.GetRoa(bgp.RouteFamily(arg.Family))
	if err != nil {
		return nil, err
	}
	l := make([]*Roa, 0, len(roas))
	for _, r := range roas {
		host, port, _ := net.SplitHostPort(r.Src)
		l = append(l, &Roa{
			As:        r.AS,
			Maxlen:    uint32(r.MaxLen),
			Prefixlen: uint32(r.Prefix.Length),
			Prefix:    r.Prefix.Prefix.String(),
			Conf: &RPKIConf{
				Address:    host,
				RemotePort: port,
			},
		})
	}
	return &GetRoaResponse{Roas: l}, nil
}
Exemple #23
0
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
}
Exemple #24
0
func (w *grpcIncomingWatcher) loop() error {
	for {
		select {
		case <-w.t.Dying():
			for _, req := range w.reqs {
				close(req.ResponseCh)
			}
			return nil
		case req := <-w.ctlCh:
			w.reqs = append(w.reqs, req)
		case ev := <-w.ch:
			msg := ev.(*watcherEventUpdateMsg)
			for _, path := range msg.pathList {
				remains := make([]*GrpcRequest, 0, len(w.reqs))
				result := &GrpcResponse{
					Data: &api.Destination{
						Prefix: path.GetNlri().String(),
						Paths:  []*api.Path{path.ToApiStruct(table.GLOBAL_RIB_NAME)},
					},
				}
				for _, req := range w.reqs {
					select {
					case <-req.EndCh:
						continue
					default:
					}
					remains = append(remains, req)
					if req.RouteFamily != bgp.RouteFamily(0) && req.RouteFamily != path.GetRouteFamily() {
						continue
					}
					if req.Name != "" && req.Name != path.GetSource().Address.String() {
						continue
					}
					req.ResponseCh <- result
				}
				w.reqs = remains
			}
		}
	}
}
Exemple #25
0
func (s *Server) neighbor(reqType int, address string, d interface{}) (interface{}, error) {
	req := NewGrpcRequest(reqType, address, bgp.RouteFamily(0), d)
	s.bgpServerCh <- req
	res := <-req.ResponseCh
	return res.Data, res.Err()
}
Exemple #26
0
func (s *Server) get(typ int, d interface{}) (interface{}, error) {
	req := NewGrpcRequest(typ, "", bgp.RouteFamily(0), d)
	s.bgpServerCh <- req
	res := <-req.ResponseCh
	return res.Data, res.Err()
}
Exemple #27
0
func (w *grpcWatcher) loop() error {
	for {
		select {
		case <-w.t.Dying():
			for _, rs := range w.reqs {
				for _, req := range rs {
					close(req.ResponseCh)
				}
			}
			return nil
		case req := <-w.ctlCh:
			var reqType watcherEventType
			switch req.RequestType {
			case REQ_MONITOR_RIB:
				tbl := req.Data.(*api.Table)
				switch tbl.Type {
				case api.Resource_GLOBAL:
					reqType = WATCHER_EVENT_BESTPATH_CHANGE
				case api.Resource_ADJ_IN:
					if tbl.PostPolicy {
						reqType = WATCHER_EVENT_POST_POLICY_UPDATE_MSG
					} else {
						reqType = WATCHER_EVENT_UPDATE_MSG
					}
				}
			case REQ_MONITOR_NEIGHBOR_PEER_STATE:
				reqType = WATCHER_EVENT_STATE_CHANGE
			}
			reqs := w.reqs[reqType]
			if reqs == nil {
				reqs = make([]*GrpcRequest, 0, 16)
			}
			reqs = append(reqs, req)
			w.reqs[reqType] = reqs
		case ev := <-w.ch:
			sendMultiPaths := func(reqType watcherEventType, dsts [][]*table.Path) {
				for _, dst := range dsts {
					paths := make([]*api.Path, 0, len(dst))
					for _, path := range dst {
						paths = append(paths, path.ToApiStruct(table.GLOBAL_RIB_NAME))
					}
					if len(paths) == 0 {
						continue
					}
					remains := make([]*GrpcRequest, 0, len(w.reqs[reqType]))
					result := &GrpcResponse{
						Data: &api.Destination{
							Prefix: dst[0].GetNlri().String(),
							Paths:  paths,
						},
					}
					for _, req := range w.reqs[reqType] {
						select {
						case <-req.EndCh:
							continue
						default:
						}
						remains = append(remains, req)
						if req.RouteFamily != bgp.RouteFamily(0) && req.RouteFamily != dst[0].GetRouteFamily() {
							continue
						}
						if req.Name != "" && req.Name != paths[0].NeighborIp {
							continue
						}
						req.ResponseCh <- result
					}
					w.reqs[reqType] = remains
				}
			}
			sendPaths := func(reqType watcherEventType, paths []*table.Path) {
				dsts := make([][]*table.Path, 0, len(paths))
				for _, path := range paths {
					if path == nil {
						continue
					}
					dsts = append(dsts, []*table.Path{path})
				}
				sendMultiPaths(reqType, dsts)
			}
			switch msg := ev.(type) {
			case *watcherEventBestPathMsg:
				if table.UseMultiplePaths.Enabled {
					sendMultiPaths(WATCHER_EVENT_BESTPATH_CHANGE, msg.multiPathList)
				} else {
					sendPaths(WATCHER_EVENT_BESTPATH_CHANGE, msg.pathList)
				}
			case *watcherEventUpdateMsg:
				if msg.postPolicy {
					sendPaths(WATCHER_EVENT_POST_POLICY_UPDATE_MSG, msg.pathList)
				} else {
					sendPaths(WATCHER_EVENT_UPDATE_MSG, msg.pathList)
				}
			case *watcherEventStateChangedMsg:
				peer := &api.Peer{
					Conf: &api.PeerConf{
						PeerAs:          msg.peerAS,
						LocalAs:         msg.localAS,
						NeighborAddress: msg.peerAddress.String(),
						Id:              msg.peerID.String(),
					},
					Info: &api.PeerState{
						PeerAs:          msg.peerAS,
						LocalAs:         msg.localAS,
						NeighborAddress: msg.peerAddress.String(),
						BgpState:        msg.state.String(),
						AdminState:      msg.adminState.String(),
					},
					Transport: &api.Transport{
						LocalAddress: msg.localAddress.String(),
						LocalPort:    uint32(msg.localPort),
						RemotePort:   uint32(msg.peerPort),
					},
				}
				reqType := WATCHER_EVENT_STATE_CHANGE
				remains := make([]*GrpcRequest, 0, len(w.reqs[reqType]))
				result := &GrpcResponse{
					Data: peer,
				}
				for _, req := range w.reqs[reqType] {
					select {
					case <-req.EndCh:
						continue
					default:
					}
					remains = append(remains, req)
					if req.Name != "" && req.Name != peer.Conf.NeighborAddress {
						continue
					}
					req.ResponseCh <- result
				}
				w.reqs[reqType] = remains
			}
		}
	}
}
Exemple #28
0
func showNeighbor(args []string) error {
	p, e := getNeighbor(args[0])
	if e != nil {
		return e
	}
	if globalOpts.Json {
		j, _ := json.Marshal(p)
		fmt.Println(string(j))
		return nil
	}

	fmt.Printf("BGP neighbor is %s, remote AS %d\n", p.Conf.RemoteIp, p.Conf.RemoteAs)
	id := "unknown"
	if p.Conf.Id != nil {
		id = p.Conf.Id.String()
	}
	fmt.Printf("  BGP version 4, remote router ID %s\n", id)
	fmt.Printf("  BGP state = %s, up for %s\n", p.Info.BgpState, formatTimedelta(int64(p.Timers.State.Uptime)-time.Now().Unix()))
	fmt.Printf("  BGP OutQ = %d, Flops = %d\n", p.Info.OutQ, p.Info.Flops)
	fmt.Printf("  Hold time is %d, keepalive interval is %d seconds\n", p.Timers.State.NegotiatedHoldTime, p.Timers.State.KeepaliveInterval)
	fmt.Printf("  Configured hold time is %d, keepalive interval is %d seconds\n", p.Timers.Config.HoldTime, p.Timers.Config.KeepaliveInterval)

	fmt.Printf("  Neighbor capabilities:\n")
	caps := capabilities{}
	lookup := func(val bgp.ParameterCapabilityInterface, l capabilities) bgp.ParameterCapabilityInterface {
		for _, v := range l {
			if v.Code() == val.Code() {
				if v.Code() == bgp.BGP_CAP_MULTIPROTOCOL {
					lhs := v.(*bgp.CapMultiProtocol).CapValue
					rhs := val.(*bgp.CapMultiProtocol).CapValue
					if lhs == rhs {
						return v
					}
					continue
				}
				return v
			}
		}
		return nil
	}
	for _, c := range p.Conf.LocalCap {
		caps = append(caps, c)
	}
	for _, c := range p.Conf.RemoteCap {
		if lookup(c, caps) == nil {
			caps = append(caps, c)
		}
	}

	sort.Sort(caps)

	firstMp := true

	for _, c := range caps {
		support := ""
		if m := lookup(c, p.Conf.LocalCap); m != nil {
			support += "advertised"
		}
		if lookup(c, p.Conf.RemoteCap) != nil {
			if len(support) != 0 {
				support += " and "
			}
			support += "received"
		}

		switch c.Code() {
		case bgp.BGP_CAP_MULTIPROTOCOL:
			if firstMp {
				fmt.Printf("    %s:\n", c.Code())
				firstMp = false
			}
			m := c.(*bgp.CapMultiProtocol).CapValue
			fmt.Printf("        %s:\t%s\n", m, support)
		case bgp.BGP_CAP_GRACEFUL_RESTART:
			fmt.Printf("    %s:\t%s\n", c.Code(), support)
			grStr := func(g *bgp.CapGracefulRestart) string {
				str := ""
				if len(g.Tuples) > 0 {
					str += fmt.Sprintf("restart time %d sec", g.Time)
				}
				if g.Flags == 0x08 {
					if len(str) > 0 {
						str += ", "
					}
					str += "restart flag set"
				}
				if len(str) > 0 {
					str += "\n"
				}
				for _, t := range g.Tuples {
					str += fmt.Sprintf("	    %s", bgp.AfiSafiToRouteFamily(t.AFI, t.SAFI))
					if t.Flags == 0x80 {
						str += ", forward flag set"
					}
					str += "\n"
				}
				return str
			}
			if m := lookup(c, p.Conf.LocalCap); m != nil {
				g := m.(*bgp.CapGracefulRestart)
				if s := grStr(g); len(s) > 0 {
					fmt.Printf("        Local: %s", s)
				}
			}
			if m := lookup(c, p.Conf.RemoteCap); m != nil {
				g := m.(*bgp.CapGracefulRestart)
				if s := grStr(g); len(s) > 0 {
					fmt.Printf("        Remote: %s", s)
				}
			}
		default:
			fmt.Printf("    %s:\t%s\n", c.Code(), support)
		}
	}
	fmt.Print("  Message statistics:\n")
	fmt.Print("                         Sent       Rcvd\n")
	fmt.Printf("    Opens:         %10d %10d\n", p.Info.Messages.Sent.OPEN, p.Info.Messages.Received.OPEN)
	fmt.Printf("    Notifications: %10d %10d\n", p.Info.Messages.Sent.NOTIFICATION, p.Info.Messages.Received.NOTIFICATION)
	fmt.Printf("    Updates:       %10d %10d\n", p.Info.Messages.Sent.UPDATE, p.Info.Messages.Received.UPDATE)
	fmt.Printf("    Keepalives:    %10d %10d\n", p.Info.Messages.Sent.KEEPALIVE, p.Info.Messages.Received.KEEPALIVE)
	fmt.Printf("    Route Refesh:  %10d %10d\n", p.Info.Messages.Sent.REFRESH, p.Info.Messages.Received.REFRESH)
	fmt.Printf("    Discarded:     %10d %10d\n", p.Info.Messages.Sent.DISCARDED, p.Info.Messages.Received.DISCARDED)
	fmt.Printf("    Total:         %10d %10d\n", p.Info.Messages.Sent.TOTAL, p.Info.Messages.Received.TOTAL)
	fmt.Print("  Route statistics:\n")
	fmt.Printf("    Advertised:    %10d\n", p.Info.Advertised)
	fmt.Printf("    Received:      %10d\n", p.Info.Received)
	fmt.Printf("    Accepted:      %10d\n", p.Info.Accepted)
	if len(p.Conf.PrefixLimits) > 0 {
		fmt.Println("  Prefix Limits:")
		for _, c := range p.Conf.PrefixLimits {
			fmt.Printf("    %s:\tMaximum prefixes allowed %d", bgp.RouteFamily(c.Family), c.MaxPrefixes)
			if c.ShutdownThresholdPct > 0 {
				fmt.Printf(", Threshold for warning message %d%%\n", c.ShutdownThresholdPct)
			} else {
				fmt.Printf("\n")
			}
		}
	}

	return nil
}
Exemple #29
0
func NewMonitorCmd() *cobra.Command {

	monitor := func(recver interface {
		Recv() (*table.Destination, error)
	}) {
		for {
			dst, err := recver.Recv()
			if err == io.EOF {
				break
			} else if err != nil {
				exitWithError(err)
			}
			if globalOpts.Json {
				j, _ := json.Marshal(dst.GetAllKnownPathList())
				fmt.Println(string(j))
			} else {
				ShowRoute(dst.GetAllKnownPathList(), false, false, false, true, false)
			}
		}
	}

	ribCmd := &cobra.Command{
		Use: CMD_RIB,
		Run: func(cmd *cobra.Command, args []string) {
			family, err := checkAddressFamily(bgp.RouteFamily(0))
			if err != nil {
				exitWithError(err)
			}
			recver, err := client.MonitorRIB(family)
			if err != nil {
				exitWithError(err)
			}
			monitor(recver)
		},
	}
	ribCmd.PersistentFlags().StringVarP(&subOpts.AddressFamily, "address-family", "a", "", "address family")

	globalCmd := &cobra.Command{
		Use: CMD_GLOBAL,
	}
	globalCmd.AddCommand(ribCmd)

	neighborCmd := &cobra.Command{
		Use: CMD_NEIGHBOR,
		Run: func(cmd *cobra.Command, args []string) {
			var names []string
			if len(args) > 0 {
				names = []string{args[0]}
			}
			stream, err := client.MonitorNeighborState(names...)
			if err != nil {
				exitWithError(err)
			}
			for {
				s, err := stream.Recv()
				if err == io.EOF {
					break
				} else if err != nil {
					exitWithError(err)
				}
				if globalOpts.Json {
					j, _ := json.Marshal(s)
					fmt.Println(string(j))
				} else {
					fmt.Printf("[NEIGH] %s fsm: %s admin: %s\n", s.Config.NeighborAddress, s.State.SessionState, s.State.AdminState)
				}
			}
		},
	}

	adjInCmd := &cobra.Command{
		Use: CMD_ADJ_IN,
		Run: func(cmd *cobra.Command, args []string) {
			name := ""
			if len(args) > 0 {
				remoteIP := net.ParseIP(args[0])
				if remoteIP == nil {
					exitWithError(fmt.Errorf("invalid ip address: %s", args[0]))
				}
				name = args[0]
			}
			family, err := checkAddressFamily(bgp.RouteFamily(0))
			if err != nil {
				exitWithError(err)
			}
			recver, err := client.MonitorAdjRIBIn(name, family)
			if err != nil {
				exitWithError(err)
			}
			monitor(recver)
		},
	}
	adjInCmd.PersistentFlags().StringVarP(&subOpts.AddressFamily, "address-family", "a", "", "address family")

	monitorCmd := &cobra.Command{
		Use: CMD_MONITOR,
	}
	monitorCmd.AddCommand(globalCmd)
	monitorCmd.AddCommand(neighborCmd)
	monitorCmd.AddCommand(adjInCmd)

	return monitorCmd
}
Exemple #30
0
func main() {
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGUSR1)

	var opts struct {
		ConfigFile      string `short:"f" long:"config-file" description:"specifying a config file"`
		ConfigType      string `short:"t" long:"config-type" description:"specifying config type (toml, yaml, json)" default:"toml"`
		LogLevel        string `short:"l" long:"log-level" description:"specifying log level"`
		LogPlain        bool   `short:"p" long:"log-plain" description:"use plain format for logging (json by default)"`
		UseSyslog       string `short:"s" long:"syslog" description:"use syslogd"`
		Facility        string `long:"syslog-facility" description:"specify syslog facility"`
		DisableStdlog   bool   `long:"disable-stdlog" description:"disable standard logging"`
		CPUs            int    `long:"cpus" description:"specify the number of CPUs to be used"`
		Ops             bool   `long:"openswitch" description:"openswitch mode"`
		GrpcHosts       string `long:"api-hosts" description:"specify the hosts that gobgpd listens on" default:":50051"`
		GracefulRestart bool   `short:"r" long:"graceful-restart" description:"flag restart-state in graceful-restart capability"`
		Dry             bool   `short:"d" long:"dry-run" description:"check configuration"`
		PProfHost       string `long:"pprof-host" description:"specify the host that gobgpd listens on for pprof" default:"localhost:6060"`
		PProfDisable    bool   `long:"pprof-disable" description:"disable pprof profiling"`
	}
	_, err := flags.Parse(&opts)
	if err != nil {
		os.Exit(1)
	}

	if opts.CPUs == 0 {
		runtime.GOMAXPROCS(runtime.NumCPU())
	} else {
		if runtime.NumCPU() < opts.CPUs {
			log.Errorf("Only %d CPUs are available but %d is specified", runtime.NumCPU(), opts.CPUs)
			os.Exit(1)
		}
		runtime.GOMAXPROCS(opts.CPUs)
	}

	if !opts.PProfDisable {
		go func() {
			log.Println(http.ListenAndServe(opts.PProfHost, nil))
		}()
	}

	switch opts.LogLevel {
	case "debug":
		log.SetLevel(log.DebugLevel)
	case "info":
		log.SetLevel(log.InfoLevel)
	default:
		log.SetLevel(log.InfoLevel)
	}

	if opts.DisableStdlog == true {
		log.SetOutput(ioutil.Discard)
	} else {
		log.SetOutput(os.Stdout)
	}

	if opts.UseSyslog != "" {
		dst := strings.SplitN(opts.UseSyslog, ":", 2)
		network := ""
		addr := ""
		if len(dst) == 2 {
			network = dst[0]
			addr = dst[1]
		}

		facility := syslog.Priority(0)
		switch opts.Facility {
		case "kern":
			facility = syslog.LOG_KERN
		case "user":
			facility = syslog.LOG_USER
		case "mail":
			facility = syslog.LOG_MAIL
		case "daemon":
			facility = syslog.LOG_DAEMON
		case "auth":
			facility = syslog.LOG_AUTH
		case "syslog":
			facility = syslog.LOG_SYSLOG
		case "lpr":
			facility = syslog.LOG_LPR
		case "news":
			facility = syslog.LOG_NEWS
		case "uucp":
			facility = syslog.LOG_UUCP
		case "cron":
			facility = syslog.LOG_CRON
		case "authpriv":
			facility = syslog.LOG_AUTHPRIV
		case "ftp":
			facility = syslog.LOG_FTP
		case "local0":
			facility = syslog.LOG_LOCAL0
		case "local1":
			facility = syslog.LOG_LOCAL1
		case "local2":
			facility = syslog.LOG_LOCAL2
		case "local3":
			facility = syslog.LOG_LOCAL3
		case "local4":
			facility = syslog.LOG_LOCAL4
		case "local5":
			facility = syslog.LOG_LOCAL5
		case "local6":
			facility = syslog.LOG_LOCAL6
		case "local7":
			facility = syslog.LOG_LOCAL7
		}

		hook, err := logrus_syslog.NewSyslogHook(network, addr, syslog.LOG_INFO|facility, "bgpd")
		if err != nil {
			log.Error("Unable to connect to syslog daemon, ", opts.UseSyslog)
			os.Exit(1)
		} else {
			log.AddHook(hook)
		}
	}

	if opts.LogPlain {
		if opts.DisableStdlog {
			log.SetFormatter(&log.TextFormatter{
				DisableColors: true,
			})
		}
	} else {
		log.SetFormatter(&log.JSONFormatter{})
	}

	configCh := make(chan *config.BgpConfigSet)
	if opts.Dry {
		go config.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh)
		c := <-configCh
		if opts.LogLevel == "debug" {
			p.Println(c)
		}
		os.Exit(0)
	}

	log.Info("gobgpd started")
	bgpServer := server.NewBgpServer()
	go bgpServer.Serve()

	// start grpc Server
	grpcServer := api.NewGrpcServer(bgpServer, opts.GrpcHosts)
	go func() {
		if err := grpcServer.Serve(); err != nil {
			log.Fatalf("failed to listen grpc port: %s", err)
		}
	}()

	if opts.Ops {
		m, err := ops.NewOpsManager(opts.GrpcHosts)
		if err != nil {
			log.Errorf("Failed to start ops config manager: %s", err)
			os.Exit(1)
		}
		log.Info("Coordination with OpenSwitch")
		m.Serve()
	} else if opts.ConfigFile != "" {
		go config.ReadConfigfileServe(opts.ConfigFile, opts.ConfigType, configCh)
	}

	var c *config.BgpConfigSet = nil
	for {
		select {
		case newConfig := <-configCh:
			var added, deleted, updated []config.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); 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 := config.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 = config.UpdateConfig(c, newConfig)
				if updatePolicy {
					log.Info("Policy config is updated")
					p := config.ConfigSetToRoutingPolicy(newConfig)
					bgpServer.UpdatePolicy(*p)
				}
				c = newConfig
			}

			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 sig := <-sigCh:
			switch sig {
			case syscall.SIGKILL, syscall.SIGTERM:
				bgpServer.Shutdown()
			case syscall.SIGUSR1:
				runtime.GC()
				debug.FreeOSMemory()
			}
		}
	}
}