Exemplo n.º 1
0
Arquivo: mrt.go Projeto: osrg/gobgp
func injectMrt(filename string, count int, skip int, onlyBest bool) error {

	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %s", err)
	}

	idx := 0

	ch := make(chan []*table.Path, 1<<20)

	go func() {

		var peers []*mrt.Peer

		for {
			buf := make([]byte, mrt.MRT_COMMON_HEADER_LEN)
			_, err := file.Read(buf)
			if err == io.EOF {
				break
			} else if err != nil {
				exitWithError(fmt.Errorf("failed to read: %s", err))
			}

			h := &mrt.MRTHeader{}
			err = h.DecodeFromBytes(buf)
			if err != nil {
				exitWithError(fmt.Errorf("failed to parse"))
			}

			buf = make([]byte, h.Len)
			_, err = file.Read(buf)
			if err != nil {
				exitWithError(fmt.Errorf("failed to read"))
			}

			msg, err := mrt.ParseMRTBody(h, buf)
			if err != nil {
				printError(fmt.Errorf("failed to parse: %s", err))
				continue
			}

			if globalOpts.Debug {
				fmt.Println(msg)
			}

			if msg.Header.Type == mrt.TABLE_DUMPv2 {
				subType := mrt.MRTSubTypeTableDumpv2(msg.Header.SubType)
				switch subType {
				case mrt.PEER_INDEX_TABLE:
					peers = msg.Body.(*mrt.PeerIndexTable).Peers
					continue
				default:
					exitWithError(fmt.Errorf("unsupported subType: %v", subType))
				}

				if peers == nil {
					exitWithError(fmt.Errorf("not found PEER_INDEX_TABLE"))
				}

				rib := msg.Body.(*mrt.Rib)
				nlri := rib.Prefix

				paths := make([]*table.Path, 0, len(rib.Entries))

				for _, e := range rib.Entries {
					if len(peers) < int(e.PeerIndex) {
						exitWithError(fmt.Errorf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers)))
					}
					source := &table.PeerInfo{
						AS: peers[e.PeerIndex].AS,
						ID: peers[e.PeerIndex].BgpId,
					}
					t := time.Unix(int64(e.OriginatedTime), 0)
					paths = append(paths, table.NewPath(source, nlri, false, e.PathAttributes, t, false))
				}

				if onlyBest {
					dst := table.NewDestination(nlri)
					for _, p := range paths {
						dst.AddNewPath(p)
					}
					best, _, _ := dst.Calculate([]string{table.GLOBAL_RIB_NAME})
					if best[table.GLOBAL_RIB_NAME] == nil {
						exitWithError(fmt.Errorf("Can't find the best %v", nlri))
					}
					paths = []*table.Path{best[table.GLOBAL_RIB_NAME]}
				}

				if idx >= skip {
					ch <- paths
				}

				idx += 1
				if idx == count+skip {
					break
				}
			}
		}

		close(ch)
	}()

	stream, err := client.AddPathByStream()
	if err != nil {
		return fmt.Errorf("failed to modpath: %s", err)
	}

	for paths := range ch {
		err = stream.Send(paths...)
		if err != nil {
			return fmt.Errorf("failed to send: %s", err)
		}
	}

	if err := stream.Close(); err != nil {
		return fmt.Errorf("failed to send: %s", err)
	}
	return nil
}
Exemplo n.º 2
0
func injectMrt(r string, filename string, count int, skip int, onlyBest bool) error {

	var resource api.Resource
	switch r {
	case CMD_GLOBAL:
		resource = api.Resource_GLOBAL
	default:
		return fmt.Errorf("unknown resource type: %s", r)
	}

	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %s", err)
	}

	idx := 0

	ch := make(chan *api.InjectMrtRequest, 1<<20)

	go func() {

		var peers []*mrt.Peer

		for {
			buf := make([]byte, mrt.MRT_COMMON_HEADER_LEN)
			_, err := file.Read(buf)
			if err == io.EOF {
				break
			} else if err != nil {
				exitWithError(fmt.Errorf("failed to read: %s", err))
			}

			h := &mrt.MRTHeader{}
			err = h.DecodeFromBytes(buf)
			if err != nil {
				exitWithError(fmt.Errorf("failed to parse"))
			}

			buf = make([]byte, h.Len)
			_, err = file.Read(buf)
			if err != nil {
				exitWithError(fmt.Errorf("failed to read"))
			}

			msg, err := mrt.ParseMRTBody(h, buf)
			if err != nil {
				printError(fmt.Errorf("failed to parse: %s", err))
				continue
			}

			if globalOpts.Debug {
				fmt.Println(msg)
			}

			if msg.Header.Type == mrt.TABLE_DUMPv2 {
				subType := mrt.MRTSubTypeTableDumpv2(msg.Header.SubType)
				var rf bgp.RouteFamily
				switch subType {
				case mrt.PEER_INDEX_TABLE:
					peers = msg.Body.(*mrt.PeerIndexTable).Peers
					continue
				case mrt.RIB_IPV4_UNICAST:
					rf = bgp.RF_IPv4_UC
				case mrt.RIB_IPV6_UNICAST:
					rf = bgp.RF_IPv6_UC
				default:
					exitWithError(fmt.Errorf("unsupported subType: %s", subType))
				}

				if peers == nil {
					exitWithError(fmt.Errorf("not found PEER_INDEX_TABLE"))
				}

				rib := msg.Body.(*mrt.Rib)
				nlri := rib.Prefix

				paths := make([]*api.Path, 0, len(rib.Entries))

				for _, e := range rib.Entries {
					if len(peers) < int(e.PeerIndex) {
						exitWithError(fmt.Errorf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers)))
					}

					if !onlyBest {
						path := &api.Path{
							Pattrs:             make([][]byte, 0),
							NoImplicitWithdraw: true,
							SourceAsn:          peers[e.PeerIndex].AS,
							SourceId:           peers[e.PeerIndex].BgpId.String(),
						}

						if rf == bgp.RF_IPv4_UC {
							path.Nlri, _ = nlri.Serialize()
						}

						for _, p := range e.PathAttributes {
							b, err := p.Serialize()
							if err != nil {
								continue
							}
							path.Pattrs = append(path.Pattrs, b)
						}

						paths = append(paths, path)
					}
				}
				if onlyBest {
					paths = func() []*api.Path {
						dst := table.NewDestination(nlri)
						pathList := make([]*table.Path, 0, len(rib.Entries))
						for _, e := range rib.Entries {
							p := table.NewPath(&table.PeerInfo{AS: peers[e.PeerIndex].AS, ID: peers[e.PeerIndex].BgpId}, nlri, false, e.PathAttributes, time.Unix(int64(e.OriginatedTime), 0), false)
							dst.AddNewPath(p)
							pathList = append(pathList, p)
						}
						best, _, _ := dst.Calculate([]string{table.GLOBAL_RIB_NAME})
						for _, p := range pathList {
							if p == best[table.GLOBAL_RIB_NAME] {
								nb, _ := nlri.Serialize()
								return []*api.Path{&api.Path{
									Nlri:               nb,
									NoImplicitWithdraw: true,
									SourceAsn:          p.GetSource().AS,
									SourceId:           p.GetSource().ID.String(),
									Pattrs: func() [][]byte {
										attrs := make([][]byte, 0)
										for _, a := range p.GetPathAttrs() {
											if b, e := a.Serialize(); e == nil {

												attrs = append(attrs, b)
											}
										}
										return attrs
									}(),
								}}
							}
						}
						exitWithError(fmt.Errorf("Can't find the best %v", nlri))
						return []*api.Path{}
					}()
				}

				if idx >= skip {
					ch <- &api.InjectMrtRequest{
						Resource: resource,
						Paths:    paths,
					}
				}

				idx += 1
				if idx == count+skip {
					break
				}
			}
		}

		close(ch)
	}()

	stream, err := client.InjectMrt(context.Background())
	if err != nil {
		return fmt.Errorf("failed to modpath: %s", err)
	}

	for arg := range ch {
		err = stream.Send(arg)
		if err != nil {
			return fmt.Errorf("failed to send: %s", err)
		}
	}

	_, err = stream.CloseAndRecv()
	if err != nil {
		return fmt.Errorf("failed to send: %s", err)
	}
	return nil
}
Exemplo n.º 3
0
func injectMrt(r string, filename string, count int, skip int) error {

	var resource api.Resource
	switch r {
	case CMD_GLOBAL:
		resource = api.Resource_GLOBAL
	default:
		return fmt.Errorf("unknown resource type: %s", r)
	}

	file, err := os.Open(filename)
	if err != nil {
		return fmt.Errorf("failed to open file: %s", err)
	}

	idx := 0

	ch := make(chan *api.InjectMrtRequest, 1<<20)

	go func() {

		var peers []*mrt.Peer

		for {
			buf := make([]byte, mrt.MRT_COMMON_HEADER_LEN)
			_, err := file.Read(buf)
			if err == io.EOF {
				break
			} else if err != nil {
				exitWithError(fmt.Errorf("failed to read: %s", err))
			}

			h := &mrt.MRTHeader{}
			err = h.DecodeFromBytes(buf)
			if err != nil {
				exitWithError(fmt.Errorf("failed to parse"))
			}

			buf = make([]byte, h.Len)
			_, err = file.Read(buf)
			if err != nil {
				exitWithError(fmt.Errorf("failed to read"))
			}

			msg, err := mrt.ParseMRTBody(h, buf)
			if err != nil {
				printError(fmt.Errorf("failed to parse: %s", err))
				continue
			}

			if globalOpts.Debug {
				fmt.Println(msg)
			}

			if msg.Header.Type == mrt.TABLE_DUMPv2 {
				subType := mrt.MRTSubTypeTableDumpv2(msg.Header.SubType)
				var rf bgp.RouteFamily
				switch subType {
				case mrt.PEER_INDEX_TABLE:
					peers = msg.Body.(*mrt.PeerIndexTable).Peers
					continue
				case mrt.RIB_IPV4_UNICAST:
					rf = bgp.RF_IPv4_UC
				case mrt.RIB_IPV6_UNICAST:
					rf = bgp.RF_IPv6_UC
				default:
					exitWithError(fmt.Errorf("unsupported subType: %s", subType))
				}

				if peers == nil {
					exitWithError(fmt.Errorf("not found PEER_INDEX_TABLE"))
				}

				rib := msg.Body.(*mrt.Rib)
				nlri := rib.Prefix

				paths := make([]*api.Path, 0, len(rib.Entries))

				for _, e := range rib.Entries {
					if len(peers) < int(e.PeerIndex) {
						exitWithError(fmt.Errorf("invalid peer index: %d (PEER_INDEX_TABLE has only %d peers)\n", e.PeerIndex, len(peers)))
					}

					path := &api.Path{
						Pattrs:             make([][]byte, 0),
						NoImplicitWithdraw: true,
						SourceAsn:          peers[e.PeerIndex].AS,
						SourceId:           peers[e.PeerIndex].BgpId.String(),
					}

					if rf == bgp.RF_IPv4_UC {
						path.Nlri, _ = nlri.Serialize()
					}

					for _, p := range e.PathAttributes {
						b, err := p.Serialize()
						if err != nil {
							continue
						}
						path.Pattrs = append(path.Pattrs, b)
					}

					paths = append(paths, path)
				}

				if idx >= skip {
					ch <- &api.InjectMrtRequest{
						Resource: resource,
						Paths:    paths,
					}
				}

				idx += 1
				if idx == count+skip {
					break
				}
			}
		}

		close(ch)
	}()

	stream, err := client.InjectMrt(context.Background())
	if err != nil {
		return fmt.Errorf("failed to modpath: %s", err)
	}

	for arg := range ch {
		err = stream.Send(arg)
		if err != nil {
			return fmt.Errorf("failed to send: %s", err)
		}
	}

	_, err = stream.CloseAndRecv()
	if err != nil {
		return fmt.Errorf("failed to send: %s", err)
	}
	return nil
}