update gobgp pkg
This commit is contained in:
668
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgp.go
generated
vendored
668
vendor/github.com/osrg/gobgp/pkg/packet/bgp/bgp.go
generated
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/github.com/osrg/gobgp/pkg/packet/bgp/prefix_sid.go
generated
vendored
2
vendor/github.com/osrg/gobgp/pkg/packet/bgp/prefix_sid.go
generated
vendored
@@ -52,7 +52,7 @@ func (s *TLV) DecodeFromBytes(data []byte) ([]byte, error) {
|
||||
p++
|
||||
s.Length = binary.BigEndian.Uint16(data[p : p+2])
|
||||
|
||||
if len(data) < s.Len() {
|
||||
if s.Len() < prefixSIDtlvHdrLen || len(data) < s.Len() {
|
||||
return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
|
||||
}
|
||||
|
||||
|
||||
967
vendor/github.com/osrg/gobgp/pkg/packet/bgp/sr_policy.go
generated
vendored
Normal file
967
vendor/github.com/osrg/gobgp/pkg/packet/bgp/sr_policy.go
generated
vendored
Normal file
@@ -0,0 +1,967 @@
|
||||
package bgp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
api "github.com/osrg/gobgp/api"
|
||||
)
|
||||
|
||||
type SRPolicyNLRI struct {
|
||||
PrefixDefault
|
||||
rf RouteFamily
|
||||
Length uint8
|
||||
Distinguisher uint32
|
||||
Color uint32
|
||||
Endpoint []byte
|
||||
}
|
||||
|
||||
const (
|
||||
// SRPolicyIPv4NLRILen defines IPv4 SR Policy NLRI portion length in bits
|
||||
SRPolicyIPv4NLRILen = 96
|
||||
// SRPolicyIPv6NLRILen defines IPv6 SR Policy NLRI portion length in bits
|
||||
SRPolicyIPv6NLRILen = 192
|
||||
)
|
||||
|
||||
func (s *SRPolicyNLRI) Flat() map[string]string {
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) decodeFromBytes(rf RouteFamily, data []byte, options ...*MarshallingOption) error {
|
||||
if IsAddPathEnabled(true, rf, options) {
|
||||
var err error
|
||||
data, err = s.decodePathIdentifier(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
switch data[0] {
|
||||
case SRPolicyIPv4NLRILen:
|
||||
s.rf = RF_SR_POLICY_IPv4
|
||||
case SRPolicyIPv6NLRILen:
|
||||
s.rf = RF_SR_POLICY_IPv6
|
||||
default:
|
||||
msg := fmt.Sprintf("Invalid length %d for SR Policy NLRI", len(data))
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
p := 0
|
||||
s.Length = data[p] / 8
|
||||
p++
|
||||
s.Distinguisher = binary.BigEndian.Uint32(data[p : p+4])
|
||||
p += 4
|
||||
s.Color = binary.BigEndian.Uint32(data[p : p+4])
|
||||
p += 4
|
||||
s.Endpoint = data[p:]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
|
||||
buf := make([]byte, 1+s.Length)
|
||||
p := 0
|
||||
buf[0] = s.Length * 8
|
||||
p++
|
||||
binary.BigEndian.PutUint32(buf[p:p+4], s.Distinguisher)
|
||||
p += 4
|
||||
binary.BigEndian.PutUint32(buf[p:p+4], s.Color)
|
||||
p += 4
|
||||
copy(buf[p:], s.Endpoint)
|
||||
if IsAddPathEnabled(false, s.rf, options) {
|
||||
id, err := s.serializeIdentifier()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(id, buf...), nil
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) AFI() uint16 {
|
||||
afi, _ := RouteFamilyToAfiSafi(s.rf)
|
||||
return afi
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) SAFI() uint8 {
|
||||
_, safi := RouteFamilyToAfiSafi(s.rf)
|
||||
return safi
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) Len(options ...*MarshallingOption) int {
|
||||
buf, _ := s.Serialize(options...)
|
||||
return len(buf)
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) String() string {
|
||||
afi, _ := RouteFamilyToAfiSafi(s.rf)
|
||||
var endp string
|
||||
switch afi {
|
||||
case AFI_IP:
|
||||
endp = net.IP(s.Endpoint).To4().String()
|
||||
case AFI_IP6:
|
||||
endp = net.IP(s.Endpoint).To16().String()
|
||||
default:
|
||||
endp = "[" + string(s.Endpoint) + "]"
|
||||
}
|
||||
return fmt.Sprintf("{ Length: %d (bytes), Distinguisher: %d, Color %d, Endpoint: %s }", s.Length, s.Distinguisher, s.Color, endp)
|
||||
}
|
||||
|
||||
func (s *SRPolicyNLRI) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Length uint8 `json:"length"`
|
||||
Distinguisher uint32 `json:"distinguisher"`
|
||||
Color uint32 `json:"color"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
}{
|
||||
Length: s.Length,
|
||||
Distinguisher: s.Distinguisher,
|
||||
Color: s.Color,
|
||||
Endpoint: string(s.Endpoint),
|
||||
})
|
||||
}
|
||||
|
||||
type SRPolicyIPv4 struct {
|
||||
SRPolicyNLRI
|
||||
}
|
||||
|
||||
func (s *SRPolicyIPv4) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
|
||||
return s.decodeFromBytes(s.rf, data)
|
||||
}
|
||||
|
||||
func NewSRPolicyIPv4(l uint32, d uint32, c uint32, ep []byte) *SRPolicyIPv4 {
|
||||
return &SRPolicyIPv4{
|
||||
SRPolicyNLRI: SRPolicyNLRI{
|
||||
rf: RF_SR_POLICY_IPv4,
|
||||
Length: uint8(l / 8),
|
||||
Distinguisher: d,
|
||||
Color: c,
|
||||
Endpoint: ep,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type SRPolicyIPv6 struct {
|
||||
SRPolicyNLRI
|
||||
}
|
||||
|
||||
func (s *SRPolicyIPv6) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
|
||||
return s.decodeFromBytes(s.rf, data)
|
||||
}
|
||||
|
||||
func NewSRPolicyIPv6(l uint32, d uint32, c uint32, ep []byte) *SRPolicyIPv6 {
|
||||
return &SRPolicyIPv6{
|
||||
SRPolicyNLRI: SRPolicyNLRI{
|
||||
rf: RF_SR_POLICY_IPv6,
|
||||
Length: uint8(l / 8),
|
||||
Distinguisher: d,
|
||||
Color: c,
|
||||
Endpoint: ep,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type TunnelEncapSubTLVSRPreference struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
Preference uint32
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPreference) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Second byte carries the length of SR Preference SubTLV
|
||||
if t.Length != 6 {
|
||||
msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRPreference length: %d", t.Length)
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
t.Flags = value[0]
|
||||
t.Preference = binary.BigEndian.Uint32(value[2:6])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPreference) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 6)
|
||||
buf[0] = t.Flags
|
||||
binary.BigEndian.PutUint32(buf[2:6], t.Preference)
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPreference) String() string {
|
||||
return fmt.Sprintf("{Flags: 0x%02x, Preference: %d}", t.Flags, t.Preference)
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPreference) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Flags uint8 `json:"flags"`
|
||||
Preference uint32 `json:"preference"`
|
||||
}{
|
||||
Type: t.Type,
|
||||
Flags: t.Flags,
|
||||
Preference: t.Preference,
|
||||
})
|
||||
}
|
||||
|
||||
func NewTunnelEncapSubTLVSRPreference(flags uint32, preference uint32) *TunnelEncapSubTLVSRPreference {
|
||||
return &TunnelEncapSubTLVSRPreference{
|
||||
TunnelEncapSubTLV: TunnelEncapSubTLV{
|
||||
Type: ENCAP_SUBTLV_TYPE_SRPREFERENCE,
|
||||
Length: 6,
|
||||
},
|
||||
Flags: uint8(flags),
|
||||
Preference: preference,
|
||||
}
|
||||
}
|
||||
|
||||
type TunnelEncapSubTLVSRPriority struct {
|
||||
TunnelEncapSubTLV
|
||||
Priority uint8
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPriority) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Second byte carries the length of SR Preference SubTLV
|
||||
if t.Length != 2 {
|
||||
msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRPriority length: %d", t.Length)
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
t.Priority = value[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPriority) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 1+1)
|
||||
buf[0] = t.Priority
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPriority) String() string {
|
||||
return fmt.Sprintf("{Priority: %d}", t.Priority)
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRPriority) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Priority uint8 `json:"priority"`
|
||||
}{
|
||||
Type: t.Type,
|
||||
Priority: t.Priority,
|
||||
})
|
||||
}
|
||||
|
||||
func NewTunnelEncapSubTLVSRPriority(priority uint8) *TunnelEncapSubTLVSRPriority {
|
||||
return &TunnelEncapSubTLVSRPriority{
|
||||
TunnelEncapSubTLV: TunnelEncapSubTLV{
|
||||
Type: ENCAP_SUBTLV_TYPE_SRPRIORITY,
|
||||
Length: 2,
|
||||
},
|
||||
Priority: priority,
|
||||
}
|
||||
}
|
||||
|
||||
type TunnelEncapSubTLVSRCandidatePathName struct {
|
||||
TunnelEncapSubTLV
|
||||
CandidatePathName string
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRCandidatePathName) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Skip Reserved byte
|
||||
t.CandidatePathName = string(value[1:t.TunnelEncapSubTLV.Len()])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRCandidatePathName) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 1+len(t.CandidatePathName))
|
||||
copy(buf[1:], t.CandidatePathName)
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRCandidatePathName) String() string {
|
||||
return fmt.Sprintf("{Candidate Path Name: %s}", t.CandidatePathName)
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRCandidatePathName) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
CandidatePathName string `json:"candidate_path_name"`
|
||||
}{
|
||||
Type: t.Type,
|
||||
CandidatePathName: t.CandidatePathName,
|
||||
})
|
||||
}
|
||||
|
||||
func NewTunnelEncapSubTLVSRCandidatePathName(cpn string) *TunnelEncapSubTLVSRCandidatePathName {
|
||||
return &TunnelEncapSubTLVSRCandidatePathName{
|
||||
TunnelEncapSubTLV: TunnelEncapSubTLV{
|
||||
Type: ENCAP_SUBTLV_TYPE_SRCANDIDATE_PATH_NAME,
|
||||
Length: uint16(len(cpn) + 1), // length of Candidate Path name string + 1 Reserved byte
|
||||
},
|
||||
CandidatePathName: cpn,
|
||||
}
|
||||
}
|
||||
|
||||
type SRENLPValue uint8
|
||||
|
||||
const (
|
||||
// ENLPType1 Indicates to push an IPv4 Explicit NULL label on an unlabeled IPv4
|
||||
// packet, but do not push an IPv6 Explicit NULL label on an
|
||||
// unlabeled IPv6 packet.
|
||||
ENLPType1 SRENLPValue = 1
|
||||
// ENLPType2 Indicates to push an IPv6 Explicit NULL label on an unlabeled IPv6
|
||||
// packet, but do not push an IPv4 Explicit NULL label on an
|
||||
// unlabeled IPv4 packet.
|
||||
ENLPType2 SRENLPValue = 2
|
||||
// ENLPType3 Indicates to push an IPv4 Explicit NULL label on an unlabeled IPv4
|
||||
// packet, and push an IPv6 Explicit NULL label on an unlabeled
|
||||
// IPv6 packet.
|
||||
ENLPType3 SRENLPValue = 3
|
||||
// ENLPType4 Indicates to not push an Explicit NULL label.
|
||||
ENLPType4 SRENLPValue = 4
|
||||
)
|
||||
|
||||
type TunnelEncapSubTLVSRENLP struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
ENLP SRENLPValue
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRENLP) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Second byte carries the length of SR Preference SubTLV
|
||||
if t.Length != 3 {
|
||||
msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRENLP length: %d", t.Length)
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
t.Flags = value[0]
|
||||
switch SRENLPValue(value[2]) {
|
||||
case ENLPType1:
|
||||
case ENLPType2:
|
||||
case ENLPType3:
|
||||
case ENLPType4:
|
||||
default:
|
||||
msg := fmt.Sprintf("Invalid ENLP Type: %d", value[2])
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
t.ENLP = SRENLPValue(value[2])
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRENLP) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, t.Length)
|
||||
buf[0] = t.Flags
|
||||
buf[2] = byte(t.ENLP)
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRENLP) String() string {
|
||||
return fmt.Sprintf("{Flags: 0x%02x, ENLP Type: %d}", t.Flags, t.ENLP)
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRENLP) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Flags uint8 `json:"flags"`
|
||||
ENLP uint8 `json:"enlp"`
|
||||
}{
|
||||
Type: t.Type,
|
||||
Flags: t.Flags,
|
||||
ENLP: uint8(t.ENLP),
|
||||
})
|
||||
}
|
||||
|
||||
func NewTunnelEncapSubTLVSRENLP(flags uint32, enlp SRENLPValue) *TunnelEncapSubTLVSRENLP {
|
||||
return &TunnelEncapSubTLVSRENLP{
|
||||
TunnelEncapSubTLV: TunnelEncapSubTLV{
|
||||
Type: ENCAP_SUBTLV_TYPE_SRENLP,
|
||||
Length: 3,
|
||||
},
|
||||
Flags: uint8(flags),
|
||||
ENLP: enlp,
|
||||
}
|
||||
}
|
||||
|
||||
type BSID struct {
|
||||
Value []byte
|
||||
}
|
||||
|
||||
func (b *BSID) String() string {
|
||||
switch len(b.Value) {
|
||||
case 0:
|
||||
return "n/a"
|
||||
case 4:
|
||||
bsid := binary.BigEndian.Uint32(b.Value)
|
||||
bsid >>= 12
|
||||
return strconv.Itoa(int(bsid))
|
||||
case 16:
|
||||
return net.IP(b.Value).To16().String()
|
||||
default:
|
||||
return "invalid"
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BSID) Serialize() []byte {
|
||||
return b.Value
|
||||
}
|
||||
func (b *BSID) Len() int {
|
||||
return len(b.Value)
|
||||
}
|
||||
|
||||
func NewBSID(v []byte) (*BSID, error) {
|
||||
var bsid *BSID
|
||||
switch len(v) {
|
||||
case 0:
|
||||
case 4:
|
||||
t := binary.BigEndian.Uint32(v)
|
||||
t <<= 12
|
||||
bsid = &BSID{
|
||||
Value: make([]byte, len(v)),
|
||||
}
|
||||
binary.BigEndian.PutUint32(bsid.Value, t)
|
||||
case 16:
|
||||
bsid = &BSID{
|
||||
Value: make([]byte, len(v)),
|
||||
}
|
||||
copy(bsid.Value, v)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid length %d", len(v))
|
||||
}
|
||||
|
||||
return bsid, nil
|
||||
}
|
||||
|
||||
type TunnelEncapSubTLVSRBSID struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
BSID *BSID
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRBSID) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
// Check Sub TLV length, only 3 possible length are allowed
|
||||
switch t.Length {
|
||||
case 2: // No BSID, do not initializing BSID struct
|
||||
case 6:
|
||||
fallthrough
|
||||
case 18:
|
||||
t.BSID = &BSID{
|
||||
Value: make([]byte, t.Length-2),
|
||||
}
|
||||
copy(t.BSID.Value, value[2:t.Length])
|
||||
default:
|
||||
msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRBSID length: %d", t.Length)
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
t.Flags = value[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRBSID) Serialize() ([]byte, error) {
|
||||
l := 2
|
||||
if t.BSID != nil {
|
||||
l += t.BSID.Len()
|
||||
}
|
||||
buf := make([]byte, l) // 1st byte Flags, 2nd byte Reserved, 3rd+ BSID
|
||||
buf[0] = t.Flags
|
||||
if t.BSID != nil {
|
||||
bsid := t.BSID.Serialize()
|
||||
copy(buf[2:], bsid)
|
||||
}
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRBSID) String() string {
|
||||
return fmt.Sprintf("{S-Flag: %t, I-Flag: %t, BSID: %s}", t.Flags&0x80 == 0x80, t.Flags&0x40 == 0x40, t.BSID.String())
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRBSID) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Flags uint8 `json:"flags"`
|
||||
BSID string `json:"binding_sid,omitempty"`
|
||||
}{
|
||||
Type: t.Type,
|
||||
Flags: t.Flags,
|
||||
BSID: t.BSID.String(),
|
||||
})
|
||||
}
|
||||
|
||||
type TunnelEncapSubTLVSRv6BSID struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
BSID *BSID
|
||||
EPBAS *SRv6EndpointBehaviorStructure
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRv6BSID) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
t.Flags = value[0]
|
||||
t.BSID, err = NewBSID(value[2:t.Length])
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRv6BSID) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, t.Length)
|
||||
buf[0] = t.Flags
|
||||
copy(buf[2:t.BSID.Len()], t.BSID.Serialize())
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRv6BSID) String() string {
|
||||
return fmt.Sprintf("{S-Flag: %t, I-Flag: %t, B-Flag: %t, BSID: %s}", t.Flags&0x80 == 0x80, t.Flags&0x40 == 0x40, t.Flags&0x20 == 0x20, t.BSID.String())
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRv6BSID) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Flags uint8 `json:"flags"`
|
||||
BSID string `json:"binding_sid,omitempty"`
|
||||
}{
|
||||
Type: t.Type,
|
||||
Flags: t.Flags,
|
||||
BSID: t.BSID.String(),
|
||||
})
|
||||
}
|
||||
|
||||
// SegmentType defines a type of Segment in Segment List
|
||||
type SegmentType int
|
||||
|
||||
const (
|
||||
// TypeA Segment Sub-TLV encodes a single SR-MPLS SID
|
||||
TypeA SegmentType = 1
|
||||
// TypeB Segment Sub-TLV encodes a single SRv6 SID.
|
||||
TypeB SegmentType = 13
|
||||
// TypeC Segment Sub-TLV encodes an IPv4 node address, SR Algorithm
|
||||
// and an optional SR-MPLS SID
|
||||
TypeC SegmentType = 3
|
||||
// TypeD Segment Sub-TLV encodes an IPv6 node address, SR Algorithm
|
||||
// and an optional SR-MPLS SID.
|
||||
TypeD SegmentType = 4
|
||||
// TypeE Segment Sub-TLV encodes an IPv4 node address, a local
|
||||
// interface Identifier (Local Interface ID) and an optional SR-MPLS
|
||||
// SID.
|
||||
TypeE SegmentType = 5
|
||||
// TypeF Segment Sub-TLV encodes an adjacency local address, an
|
||||
// adjacency remote address and an optional SR-MPLS SID.
|
||||
TypeF SegmentType = 6
|
||||
// TypeG Segment Sub-TLV encodes an IPv6 Link Local adjacency with
|
||||
// IPv6 local node address, a local interface identifier (Local
|
||||
// Interface ID), IPv6 remote node address , a remote interface
|
||||
// identifier (Remote Interface ID) and an optional SR-MPLS SID.
|
||||
TypeG SegmentType = 7
|
||||
// TypeH Segment Sub-TLV encodes an adjacency local address, an
|
||||
// adjacency remote address and an optional SR-MPLS SID.
|
||||
TypeH SegmentType = 8
|
||||
// TypeI Segment Sub-TLV encodes an IPv6 node address, SR Algorithm
|
||||
// and an optional SRv6 SID.
|
||||
TypeI SegmentType = 14
|
||||
// TypeJ Segment Sub-TLV encodes an IPv6 Link Local adjacency with
|
||||
// local node address, a local interface identifier (Local Interface
|
||||
// ID), remote IPv6 node address, a remote interface identifier (Remote
|
||||
// Interface ID) and an optional SRv6 SID.
|
||||
TypeJ SegmentType = 15
|
||||
// TypeK Segment Sub-TLV encodes an adjacency local address, an
|
||||
// adjacency remote address and an optional SRv6 SID.
|
||||
TypeK SegmentType = 16
|
||||
)
|
||||
|
||||
// Weight sub-TLV specifies the weight associated to a given segment list.
|
||||
type SegmentListWeight struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
Weight uint32
|
||||
}
|
||||
|
||||
func (s *SegmentListWeight) DecodeFromBytes(data []byte) error {
|
||||
value, err := s.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
s.Flags = value[0]
|
||||
s.Weight = binary.BigEndian.Uint32(value[2:6])
|
||||
return nil
|
||||
}
|
||||
func (s *SegmentListWeight) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 6)
|
||||
buf[0] = s.Flags
|
||||
binary.BigEndian.PutUint32(buf[2:6], s.Weight)
|
||||
return s.TunnelEncapSubTLV.Serialize(buf)
|
||||
}
|
||||
func (s *SegmentListWeight) String() string {
|
||||
return fmt.Sprintf("{Flags: 0x%02x, Weight: %d}", s.Flags, s.Weight)
|
||||
}
|
||||
|
||||
func (s *SegmentListWeight) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Flags uint8 `json:"flags"`
|
||||
Weight uint32 `json:"weight,omitempty"`
|
||||
}{
|
||||
Type: s.Type,
|
||||
Flags: s.Flags,
|
||||
Weight: s.Weight,
|
||||
})
|
||||
}
|
||||
|
||||
type SegmentTypeA struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
Label uint32
|
||||
}
|
||||
|
||||
func (s *SegmentTypeA) DecodeFromBytes(data []byte) error {
|
||||
value, err := s.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
s.Flags = value[0]
|
||||
s.Label = binary.BigEndian.Uint32(value[2:6])
|
||||
return nil
|
||||
}
|
||||
func (s *SegmentTypeA) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 6)
|
||||
buf[0] = s.Flags
|
||||
binary.BigEndian.PutUint32(buf[2:6], s.Label)
|
||||
return s.TunnelEncapSubTLV.Serialize(buf)
|
||||
}
|
||||
func (s *SegmentTypeA) String() string {
|
||||
return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Label: %d TC: %d S: %t TTL: %d}",
|
||||
s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10,
|
||||
s.Label>>12, s.Label&0x00000e00>>9, s.Label&0x00000100 == 0x00000100, s.Label&0x000000ff)
|
||||
}
|
||||
|
||||
func (s *SegmentTypeA) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
VFlag bool `json:"v_flag"`
|
||||
AFlag bool `json:"a_flag"`
|
||||
SFlag bool `json:"s_flag"`
|
||||
BFlag bool `json:"b_flag"`
|
||||
Label uint32 `json:"label"`
|
||||
TC uint8 `json:"tc"`
|
||||
S bool `json:"s"`
|
||||
TTL uint8 `json:"ttl"`
|
||||
}{
|
||||
Type: s.Type,
|
||||
VFlag: s.Flags&0x80 == 0x80,
|
||||
AFlag: s.Flags&0x40 == 0x40,
|
||||
SFlag: s.Flags&0x20 == 0x20,
|
||||
BFlag: s.Flags&0x10 == 0x10,
|
||||
Label: s.Label >> 12,
|
||||
TC: uint8(s.Label & 0x00000e00 >> 9),
|
||||
S: s.Label&0x00000100 == 0x00000100,
|
||||
TTL: uint8(s.Label & 0x000000ff),
|
||||
})
|
||||
}
|
||||
|
||||
type SRBehavior int32
|
||||
|
||||
const (
|
||||
RESERVED SRBehavior = SRBehavior(api.SRv6Behavior_RESERVED)
|
||||
END SRBehavior = SRBehavior(api.SRv6Behavior_END)
|
||||
END_WITH_PSP SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP)
|
||||
END_WITH_USP SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_USP)
|
||||
END_WITH_PSP_USP SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP_USP)
|
||||
ENDX SRBehavior = SRBehavior(api.SRv6Behavior_ENDX)
|
||||
ENDX_WITH_PSP SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP)
|
||||
ENDX_WITH_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_USP)
|
||||
ENDX_WITH_PSP_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP_USP)
|
||||
ENDT SRBehavior = SRBehavior(api.SRv6Behavior_ENDT)
|
||||
ENDT_WITH_PSP SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP)
|
||||
ENDT_WITH_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_USP)
|
||||
ENDT_WITH_PSP_USP SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP_USP)
|
||||
END_B6_ENCAPS SRBehavior = SRBehavior(api.SRv6Behavior_END_B6_ENCAPS)
|
||||
END_BM SRBehavior = SRBehavior(api.SRv6Behavior_END_BM)
|
||||
END_DX6 SRBehavior = SRBehavior(api.SRv6Behavior_END_DX6)
|
||||
END_DX4 SRBehavior = SRBehavior(api.SRv6Behavior_END_DX4)
|
||||
END_DT6 SRBehavior = SRBehavior(api.SRv6Behavior_END_DT6)
|
||||
END_DT4 SRBehavior = SRBehavior(api.SRv6Behavior_END_DT4)
|
||||
END_DT46 SRBehavior = SRBehavior(api.SRv6Behavior_END_DT46)
|
||||
END_DX2 SRBehavior = SRBehavior(api.SRv6Behavior_END_DX2)
|
||||
END_DX2V SRBehavior = SRBehavior(api.SRv6Behavior_END_DX2V)
|
||||
END_DT2U SRBehavior = SRBehavior(api.SRv6Behavior_RESERVED)
|
||||
END_DT2M SRBehavior = SRBehavior(api.SRv6Behavior_END_DT2M)
|
||||
END_B6_ENCAPS_Red SRBehavior = SRBehavior(api.SRv6Behavior_END_B6_ENCAPS_Red)
|
||||
END_WITH_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_USD)
|
||||
END_WITH_PSP_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP_USD)
|
||||
END_WITH_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_USP_USD)
|
||||
END_WITH_PSP_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_END_WITH_PSP_USP_USD)
|
||||
ENDX_WITH_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_USD)
|
||||
ENDX_WITH_PSP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP_USD)
|
||||
ENDX_WITH_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_USP_USD)
|
||||
ENDX_WITH_PSP_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDX_WITH_PSP_USP_USD)
|
||||
ENDT_WITH_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_USD)
|
||||
ENDT_WITH_PSP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP_USD)
|
||||
ENDT_WITH_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_USP_USD)
|
||||
ENDT_WITH_PSP_USP_USD SRBehavior = SRBehavior(api.SRv6Behavior_ENDT_WITH_PSP_USP_USD)
|
||||
)
|
||||
|
||||
type SRv6EndpointBehaviorStructure struct {
|
||||
Behavior SRBehavior
|
||||
BlockLen uint8
|
||||
NodeLen uint8
|
||||
FuncLen uint8
|
||||
ArgLen uint8
|
||||
}
|
||||
|
||||
func (s *SRv6EndpointBehaviorStructure) DecodeFromBytes(data []byte) error {
|
||||
if len(data) < 8 {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Malformed BGP message")
|
||||
}
|
||||
behavior := binary.BigEndian.Uint16(data[0:2])
|
||||
s.Behavior = SRBehavior(behavior)
|
||||
s.BlockLen = data[4]
|
||||
s.NodeLen = data[5]
|
||||
s.FuncLen = data[6]
|
||||
s.ArgLen = data[7]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SRv6EndpointBehaviorStructure) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 8)
|
||||
binary.BigEndian.PutUint16(buf[0:2], uint16(s.Behavior))
|
||||
buf[4] = s.BlockLen
|
||||
buf[5] = s.NodeLen
|
||||
buf[6] = s.FuncLen
|
||||
buf[7] = s.ArgLen
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (s *SRv6EndpointBehaviorStructure) String() string {
|
||||
return fmt.Sprintf("{Behavior: %s, BlockLen: %d, NodeLen: %d, FuncLen: %d, ArgLen: %d}",
|
||||
api.SRv6Behavior(s.Behavior).String(), s.BlockLen, s.NodeLen, s.FuncLen, s.ArgLen)
|
||||
}
|
||||
|
||||
func (s *SRv6EndpointBehaviorStructure) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Behavior SRBehavior `json:"behavior"`
|
||||
BlockLen uint8 `json:"block_Len"`
|
||||
NodeLen uint8 `json:"node_len"`
|
||||
FuncLen uint8 `json:"func_len"`
|
||||
ArgLen uint8 `json:"arg_len"`
|
||||
}{
|
||||
Behavior: s.Behavior,
|
||||
BlockLen: s.BlockLen,
|
||||
NodeLen: s.NodeLen,
|
||||
FuncLen: s.FuncLen,
|
||||
ArgLen: s.ArgLen,
|
||||
})
|
||||
}
|
||||
|
||||
type SegmentTypeB struct {
|
||||
TunnelEncapSubTLV
|
||||
Flags uint8
|
||||
SID []byte
|
||||
SRv6EBS *SRv6EndpointBehaviorStructure
|
||||
}
|
||||
|
||||
func (s *SegmentTypeB) DecodeFromBytes(data []byte) error {
|
||||
value, err := s.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
if len(value) < 18 {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Malformed BGP message")
|
||||
}
|
||||
s.Flags = value[0]
|
||||
s.SID = value[2:18]
|
||||
|
||||
if len(value) == 26 {
|
||||
s.SRv6EBS = &SRv6EndpointBehaviorStructure{}
|
||||
err = s.SRv6EBS.DecodeFromBytes(value[18:])
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (s *SegmentTypeB) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 18)
|
||||
buf[0] = s.Flags
|
||||
copy(buf[2:], s.SID)
|
||||
if s.SRv6EBS != nil {
|
||||
if ebs, _ := s.SRv6EBS.Serialize(); ebs != nil {
|
||||
buf = append(buf, ebs...)
|
||||
}
|
||||
}
|
||||
|
||||
return s.TunnelEncapSubTLV.Serialize(buf)
|
||||
}
|
||||
func (s *SegmentTypeB) String() string {
|
||||
if s.SRv6EBS == nil {
|
||||
return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Sid: %s}",
|
||||
s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10, net.IP(s.SID).To16().String())
|
||||
} else {
|
||||
return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Sid: %s, Ebs: %s}",
|
||||
s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10, net.IP(s.SID).To16().String(),
|
||||
s.SRv6EBS.String())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *SegmentTypeB) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
VFlag bool `json:"v_flag"`
|
||||
AFlag bool `json:"a_flag"`
|
||||
SFlag bool `json:"s_flag"`
|
||||
BFlag bool `json:"b_flag"`
|
||||
Sid string `json:"sid"`
|
||||
SRv6EBS *SRv6EndpointBehaviorStructure `json:"endpointBehaviorStructure"`
|
||||
}{
|
||||
Type: s.Type,
|
||||
VFlag: s.Flags&0x80 == 0x80,
|
||||
AFlag: s.Flags&0x40 == 0x40,
|
||||
SFlag: s.Flags&0x20 == 0x20,
|
||||
BFlag: s.Flags&0x10 == 0x10,
|
||||
Sid: net.IP(s.SID).To16().String(),
|
||||
SRv6EBS: s.SRv6EBS,
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
// SegmentListSubTLVWeight defines code for Segment List's Weight sub-TLV
|
||||
SegmentListSubTLVWeight = 9
|
||||
)
|
||||
|
||||
type TunnelEncapSubTLVSRSegmentList struct {
|
||||
TunnelEncapSubTLV
|
||||
Weight *SegmentListWeight
|
||||
Segments []TunnelEncapSubTLVInterface
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRSegmentList) DecodeFromBytes(data []byte) error {
|
||||
value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data)
|
||||
if err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
if len(value) < 1 {
|
||||
return NewMessageError(BGP_ERROR_MESSAGE_HEADER_ERROR, BGP_ERROR_SUB_BAD_MESSAGE_LENGTH, nil, "Malformed BGP message")
|
||||
}
|
||||
// Skip reserved byte to access inner SubTLV type
|
||||
value = value[1:]
|
||||
var segments []TunnelEncapSubTLVInterface
|
||||
p := 0
|
||||
for p < t.TunnelEncapSubTLV.Len()-4 {
|
||||
var segment TunnelEncapSubTLVInterface
|
||||
switch SegmentType(value[0]) {
|
||||
case SegmentListSubTLVWeight:
|
||||
t.Weight = &SegmentListWeight{}
|
||||
if err := t.Weight.DecodeFromBytes(value); err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
p += t.Weight.TunnelEncapSubTLV.Len()
|
||||
value = value[t.Weight.TunnelEncapSubTLV.Len():]
|
||||
continue
|
||||
case TypeA:
|
||||
segment = &SegmentTypeA{}
|
||||
if err := segment.DecodeFromBytes(value); err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
case TypeB:
|
||||
segment = &SegmentTypeB{}
|
||||
if err := segment.DecodeFromBytes(value); err != nil {
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error())
|
||||
}
|
||||
case TypeC:
|
||||
fallthrough
|
||||
case TypeD:
|
||||
fallthrough
|
||||
case TypeE:
|
||||
fallthrough
|
||||
case TypeF:
|
||||
fallthrough
|
||||
case TypeG:
|
||||
fallthrough
|
||||
case TypeH:
|
||||
fallthrough
|
||||
case TypeI:
|
||||
fallthrough
|
||||
case TypeJ:
|
||||
fallthrough
|
||||
case TypeK:
|
||||
msg := fmt.Sprintf("Invalid SR Policy Segment SubTLV %d is not yet supported", value[0])
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
default:
|
||||
msg := fmt.Sprintf("Invalid SR Policy Segment List SubTLV %d", value[0])
|
||||
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg)
|
||||
}
|
||||
segments = append(segments, segment)
|
||||
p += segment.Len()
|
||||
value = value[segment.Len():]
|
||||
}
|
||||
if len(segments) == 0 {
|
||||
t.Segments = nil
|
||||
} else {
|
||||
t.Segments = segments
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRSegmentList) Serialize() ([]byte, error) {
|
||||
buf := make([]byte, 0)
|
||||
// Add reserved byte
|
||||
buf = append(buf, 0x0)
|
||||
if t.Weight != nil {
|
||||
wbuf, err := t.Weight.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf = append(buf, wbuf...)
|
||||
}
|
||||
for _, s := range t.Segments {
|
||||
sbuf, err := s.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buf = append(buf, sbuf...)
|
||||
}
|
||||
return t.TunnelEncapSubTLV.Serialize(buf[:])
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRSegmentList) String() string {
|
||||
msg := "{"
|
||||
if t.Weight != nil {
|
||||
msg += "Weight: " + t.Weight.String() + ","
|
||||
}
|
||||
msg += "Segment List: [ "
|
||||
for _, s := range t.Segments {
|
||||
msg += s.String() + ","
|
||||
}
|
||||
msg += " ] }"
|
||||
return msg
|
||||
}
|
||||
|
||||
func (t *TunnelEncapSubTLVSRSegmentList) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(struct {
|
||||
Type EncapSubTLVType `json:"type"`
|
||||
Weight *SegmentListWeight
|
||||
Segments []TunnelEncapSubTLVInterface
|
||||
}{
|
||||
Type: t.Type,
|
||||
Weight: t.Weight,
|
||||
Segments: t.Segments,
|
||||
})
|
||||
}
|
||||
16
vendor/github.com/osrg/gobgp/pkg/packet/bgp/validate.go
generated
vendored
16
vendor/github.com/osrg/gobgp/pkg/packet/bgp/validate.go
generated
vendored
@@ -313,7 +313,7 @@ func ValidateBGPMessage(m *BGPMessage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) (uint32, error) {
|
||||
func ValidateOpenMsg(m *BGPOpen, expectedAS uint32, myAS uint32, myId net.IP) (uint32, error) {
|
||||
if m.Version != 4 {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_UNSUPPORTED_VERSION_NUMBER, nil, fmt.Sprintf("unsupported version %d", m.Version))
|
||||
}
|
||||
@@ -331,6 +331,20 @@ func ValidateOpenMsg(m *BGPOpen, expectedAS uint32) (uint32, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rfc6286 (Autonomous-System-Wide Unique BGP Identifier for BGP-4)
|
||||
// If the BGP Identifier field of the OPEN message is zero, or if it
|
||||
// is the same as the BGP Identifier of the local BGP speaker and the
|
||||
// message is from an internal peer, then the Error Subcode is set to
|
||||
// "Bad BGP Identifier".
|
||||
routerId := m.ID
|
||||
if routerId.IsUnspecified() {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_BGP_IDENTIFIER, nil, fmt.Sprintf("bad BGP identifier %s (0.0.0.0)", routerId.String()))
|
||||
}
|
||||
if as == myAS && routerId.Equal(myId) {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_BGP_IDENTIFIER, nil, fmt.Sprintf("bad BGP identifier %s", routerId.String()))
|
||||
}
|
||||
|
||||
if expectedAS != 0 && as != expectedAS {
|
||||
return 0, NewMessageError(BGP_ERROR_OPEN_MESSAGE_ERROR, BGP_ERROR_SUB_BAD_PEER_AS, nil, fmt.Sprintf("as number mismatch expected %d, received %d", expectedAS, as))
|
||||
}
|
||||
|
||||
18
vendor/github.com/osrg/gobgp/pkg/packet/bmp/bmp.go
generated
vendored
18
vendor/github.com/osrg/gobgp/pkg/packet/bmp/bmp.go
generated
vendored
@@ -164,12 +164,11 @@ func NewBMPRouteMonitoring(p BMPPeerHeader, update *bgp.BGPMessage) *BMPMessage
|
||||
}
|
||||
|
||||
func (body *BMPRouteMonitoring) ParseBody(msg *BMPMessage, data []byte) error {
|
||||
update, err := bgp.ParseBGPMessage(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body.BGPUpdate = update
|
||||
return nil
|
||||
var err error
|
||||
|
||||
body.BGPUpdate, err = bgp.ParseBGPMessage(data)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (body *BMPRouteMonitoring) Serialize() ([]byte, error) {
|
||||
@@ -225,7 +224,7 @@ func (s *BMPStatsTLV32) ParseValue(data []byte) error {
|
||||
if s.Length != 4 {
|
||||
return fmt.Errorf("invalid length: %d bytes (%d bytes expected)", s.Length, 4)
|
||||
}
|
||||
s.Value = binary.BigEndian.Uint32(data[:8])
|
||||
s.Value = binary.BigEndian.Uint32(data[:4])
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1065,8 +1064,13 @@ func ParseBMPMessage(data []byte) (msg *BMPMessage, err error) {
|
||||
|
||||
err = msg.Body.ParseBody(msg, data)
|
||||
if err != nil {
|
||||
if msg.Header.Type == BMP_MSG_ROUTE_MONITORING {
|
||||
return msg, err
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
|
||||
6
vendor/github.com/osrg/gobgp/pkg/server/bmp.go
generated
vendored
6
vendor/github.com/osrg/gobgp/pkg/server/bmp.go
generated
vendored
@@ -115,17 +115,17 @@ func (b *bmpClient) loop() {
|
||||
}
|
||||
|
||||
if func() bool {
|
||||
ops := []watchOption{watchPeerState(true)}
|
||||
ops := []watchOption{watchPeerState(true, false)}
|
||||
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_BOTH {
|
||||
log.WithFields(
|
||||
log.Fields{"Topic": "bmp"},
|
||||
).Warn("both option for route-monitoring-policy is obsoleted")
|
||||
}
|
||||
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_PRE_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
|
||||
ops = append(ops, watchUpdate(true))
|
||||
ops = append(ops, watchUpdate(true, ""))
|
||||
}
|
||||
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_POST_POLICY || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
|
||||
ops = append(ops, watchPostUpdate(true))
|
||||
ops = append(ops, watchPostUpdate(true, ""))
|
||||
}
|
||||
if b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_LOCAL_RIB || b.c.RouteMonitoringPolicy == config.BMP_ROUTE_MONITORING_POLICY_TYPE_ALL {
|
||||
ops = append(ops, watchBestPath(true))
|
||||
|
||||
30
vendor/github.com/osrg/gobgp/pkg/server/fsm.go
generated
vendored
30
vendor/github.com/osrg/gobgp/pkg/server/fsm.go
generated
vendored
@@ -21,6 +21,7 @@ import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
@@ -714,8 +715,11 @@ func capAddPathFromConfig(pConf *config.Neighbor) bgp.ParameterCapabilityInterfa
|
||||
}
|
||||
|
||||
func capabilitiesFromConfig(pConf *config.Neighbor) []bgp.ParameterCapabilityInterface {
|
||||
fqdn, _ := os.Hostname()
|
||||
caps := make([]bgp.ParameterCapabilityInterface, 0, 4)
|
||||
caps = append(caps, bgp.NewCapRouteRefresh())
|
||||
caps = append(caps, bgp.NewCapFQDN(fqdn, ""))
|
||||
|
||||
for _, af := range pConf.AfiSafis {
|
||||
caps = append(caps, bgp.NewCapMultiProtocol(af.State.Family))
|
||||
}
|
||||
@@ -869,7 +873,8 @@ func (h *fsmHandler) afiSafiDisable(rf bgp.RouteFamily) string {
|
||||
}
|
||||
|
||||
func (h *fsmHandler) handlingError(m *bgp.BGPMessage, e error, useRevisedError bool) bgp.ErrorHandling {
|
||||
handling := bgp.ERROR_HANDLING_NONE
|
||||
// ineffectual assignment to handling (ineffassign)
|
||||
var handling bgp.ErrorHandling
|
||||
if m.Header.Type == bgp.BGP_MSG_UPDATE && useRevisedError {
|
||||
factor := e.(*bgp.MessageError)
|
||||
handling = factor.ErrorHandling
|
||||
@@ -1015,6 +1020,13 @@ func (h *fsmHandler) recvMessageWithError() (*fsmMsg, error) {
|
||||
case bgp.BGP_MSG_ROUTE_REFRESH:
|
||||
fmsg.MsgType = fsmMsgRouteRefresh
|
||||
case bgp.BGP_MSG_UPDATE:
|
||||
// if the length of h.holdTimerResetCh
|
||||
// isn't zero, the timer will be reset
|
||||
// soon anyway.
|
||||
select {
|
||||
case h.holdTimerResetCh <- true:
|
||||
default:
|
||||
}
|
||||
body := m.Body.(*bgp.BGPUpdate)
|
||||
isEBGP := h.fsm.pConf.IsEBGPPeer(h.fsm.gConf)
|
||||
isConfed := h.fsm.pConf.IsConfederationMember(h.fsm.gConf)
|
||||
@@ -1266,7 +1278,7 @@ func (h *fsmHandler) opensent(ctx context.Context) (bgp.FSMState, *fsmStateReaso
|
||||
fsm.lock.RLock()
|
||||
fsmPeerAS := fsm.pConf.Config.PeerAs
|
||||
fsm.lock.RUnlock()
|
||||
peerAs, err := bgp.ValidateOpenMsg(body, fsmPeerAS)
|
||||
peerAs, err := bgp.ValidateOpenMsg(body, fsmPeerAS, fsm.peerInfo.LocalAS, net.ParseIP(fsm.gConf.Config.RouterId))
|
||||
if err != nil {
|
||||
m, _ := fsm.sendNotificationFromErrorMsg(err.(*bgp.MessageError))
|
||||
return bgp.BGP_FSM_IDLE, newfsmStateReason(fsmInvalidMsg, m, nil)
|
||||
@@ -1569,6 +1581,14 @@ func (h *fsmHandler) openconfirm(ctx context.Context) (bgp.FSMState, *fsmStateRe
|
||||
}
|
||||
|
||||
func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) error {
|
||||
sendToStateReasonCh := func(typ fsmStateReasonType, notif *bgp.BGPMessage) {
|
||||
// probably doesn't happen but be cautious
|
||||
select {
|
||||
case h.stateReasonCh <- *newfsmStateReason(typ, notif, nil):
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
defer wg.Done()
|
||||
conn := h.conn
|
||||
fsm := h.fsm
|
||||
@@ -1603,7 +1623,7 @@ func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) er
|
||||
err = conn.SetWriteDeadline(time.Now().Add(time.Second * time.Duration(fsm.pConf.Timers.State.NegotiatedHoldTime)))
|
||||
fsm.lock.RUnlock()
|
||||
if err != nil {
|
||||
h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil)
|
||||
sendToStateReasonCh(fsmWriteFailed, nil)
|
||||
conn.Close()
|
||||
return fmt.Errorf("failed to set write deadline")
|
||||
}
|
||||
@@ -1617,7 +1637,7 @@ func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) er
|
||||
"Data": err,
|
||||
}).Warn("failed to send")
|
||||
fsm.lock.RUnlock()
|
||||
h.stateReasonCh <- *newfsmStateReason(fsmWriteFailed, nil, nil)
|
||||
sendToStateReasonCh(fsmWriteFailed, nil)
|
||||
conn.Close()
|
||||
return fmt.Errorf("closed")
|
||||
}
|
||||
@@ -1651,7 +1671,7 @@ func (h *fsmHandler) sendMessageloop(ctx context.Context, wg *sync.WaitGroup) er
|
||||
}).Warn("sent notification")
|
||||
fsm.lock.RUnlock()
|
||||
}
|
||||
h.stateReasonCh <- *newfsmStateReason(fsmNotificationSent, m, nil)
|
||||
sendToStateReasonCh(fsmNotificationSent, m)
|
||||
conn.Close()
|
||||
return fmt.Errorf("closed")
|
||||
case bgp.BGP_MSG_UPDATE:
|
||||
|
||||
101
vendor/github.com/osrg/gobgp/pkg/server/grpc_server.go
generated
vendored
101
vendor/github.com/osrg/gobgp/pkg/server/grpc_server.go
generated
vendored
@@ -64,8 +64,9 @@ func (s *server) serve() error {
|
||||
l := []net.Listener{}
|
||||
var err error
|
||||
for _, host := range strings.Split(s.hosts, ",") {
|
||||
network, address := parseHost(host)
|
||||
var lis net.Listener
|
||||
lis, err = net.Listen("tcp", host)
|
||||
lis, err = net.Listen(network, address)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "grpc",
|
||||
@@ -101,6 +102,38 @@ func (s *server) serve() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *server) ListDynamicNeighbor(r *api.ListDynamicNeighborRequest, stream api.GobgpApi_ListDynamicNeighborServer) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
fn := func(dn *api.DynamicNeighbor) {
|
||||
if err := stream.Send(&api.ListDynamicNeighborResponse{DynamicNeighbor: dn}); err != nil {
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
}
|
||||
return s.bgpServer.ListDynamicNeighbor(ctx, r, fn)
|
||||
}
|
||||
|
||||
func (s *server) ListPeerGroup(r *api.ListPeerGroupRequest, stream api.GobgpApi_ListPeerGroupServer) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
fn := func(pg *api.PeerGroup) {
|
||||
if err := stream.Send(&api.ListPeerGroupResponse{PeerGroup: pg}); err != nil {
|
||||
cancel()
|
||||
return
|
||||
}
|
||||
}
|
||||
return s.bgpServer.ListPeerGroup(ctx, r, fn)
|
||||
}
|
||||
|
||||
func parseHost(host string) (string, string) {
|
||||
const unixScheme = "unix://"
|
||||
if strings.HasPrefix(host, unixScheme) {
|
||||
return "unix", host[len(unixScheme):]
|
||||
}
|
||||
return "tcp", host
|
||||
}
|
||||
|
||||
func (s *server) ListPeer(r *api.ListPeerRequest, stream api.GobgpApi_ListPeerServer) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@@ -153,11 +186,26 @@ func toPathAPI(binNlri []byte, binPattrs [][]byte, anyNlri *any.Any, anyPattrs [
|
||||
return p
|
||||
}
|
||||
|
||||
func toPathApi(path *table.Path, v *table.Validation) *api.Path {
|
||||
func toPathApi(path *table.Path, v *table.Validation, nlri_binary, attribute_binary bool) *api.Path {
|
||||
nlri := path.GetNlri()
|
||||
anyNlri := apiutil.MarshalNLRI(nlri)
|
||||
anyPattrs := apiutil.MarshalPathAttributes(path.GetPathAttrs())
|
||||
return toPathAPI(nil, nil, anyNlri, anyPattrs, path, v)
|
||||
var binNlri []byte
|
||||
if nlri_binary {
|
||||
binNlri, _ = nlri.Serialize()
|
||||
}
|
||||
var binPattrs [][]byte
|
||||
if attribute_binary {
|
||||
pa := path.GetPathAttrs()
|
||||
binPattrs = make([][]byte, 0, len(pa))
|
||||
for _, a := range pa {
|
||||
b, e := a.Serialize()
|
||||
if e == nil {
|
||||
binPattrs = append(binPattrs, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
return toPathAPI(binNlri, binPattrs, anyNlri, anyPattrs, path, v)
|
||||
}
|
||||
|
||||
func getValidation(v map[*table.Path]*table.Validation, p *table.Path) *table.Validation {
|
||||
@@ -281,6 +329,11 @@ func api2Path(resource api.TableType, path *api.Path, isWithdraw bool) (*table.P
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO (sbezverk) At this poinnt nlri and path attributes are converted to native mode
|
||||
// need to check if update with SR Policy nlri comes with mandatory route distinguisher
|
||||
// extended community or NO_ADVERTISE community, with Tunnel Encapsulation Attribute 23
|
||||
// and tunnel type 15. If it is not the case ignore update and log an error.
|
||||
|
||||
pattrs := make([]bgp.PathAttributeInterface, 0)
|
||||
seen := make(map[bgp.BGPAttrType]struct{})
|
||||
for _, attr := range attrList {
|
||||
@@ -295,6 +348,9 @@ func api2Path(resource api.TableType, path *api.Path, isWithdraw bool) (*table.P
|
||||
case *bgp.PathAttributeNextHop:
|
||||
nexthop = a.Value.String()
|
||||
case *bgp.PathAttributeMpReachNLRI:
|
||||
if len(a.Value) == 0 {
|
||||
return nil, fmt.Errorf("invalid mp reach attribute")
|
||||
}
|
||||
nlri = a.Value[0]
|
||||
nexthop = a.Nexthop.String()
|
||||
default:
|
||||
@@ -486,20 +542,29 @@ func readApplyPolicyFromAPIStruct(c *config.ApplyPolicy, a *api.ApplyPolicy) {
|
||||
if c == nil || a == nil {
|
||||
return
|
||||
}
|
||||
f := func(a api.RouteAction) config.DefaultPolicyType {
|
||||
if a == api.RouteAction_ACCEPT {
|
||||
return config.DEFAULT_POLICY_TYPE_ACCEPT_ROUTE
|
||||
} else if a == api.RouteAction_REJECT {
|
||||
return config.DEFAULT_POLICY_TYPE_REJECT_ROUTE
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
if a.ImportPolicy != nil {
|
||||
c.Config.DefaultImportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ImportPolicy.DefaultAction)]
|
||||
c.Config.DefaultImportPolicy = f(a.ImportPolicy.DefaultAction)
|
||||
for _, p := range a.ImportPolicy.Policies {
|
||||
c.Config.ImportPolicyList = append(c.Config.ImportPolicyList, p.Name)
|
||||
}
|
||||
}
|
||||
if a.ExportPolicy != nil {
|
||||
c.Config.DefaultExportPolicy = config.IntToDefaultPolicyTypeMap[int(a.ExportPolicy.DefaultAction)]
|
||||
c.Config.DefaultExportPolicy = f(a.ExportPolicy.DefaultAction)
|
||||
for _, p := range a.ExportPolicy.Policies {
|
||||
c.Config.ExportPolicyList = append(c.Config.ExportPolicyList, p.Name)
|
||||
}
|
||||
}
|
||||
if a.InPolicy != nil {
|
||||
c.Config.DefaultInPolicy = config.IntToDefaultPolicyTypeMap[int(a.InPolicy.DefaultAction)]
|
||||
c.Config.DefaultInPolicy = f(a.InPolicy.DefaultAction)
|
||||
for _, p := range a.InPolicy.Policies {
|
||||
c.Config.InPolicyList = append(c.Config.InPolicyList, p.Name)
|
||||
}
|
||||
@@ -668,6 +733,10 @@ func newNeighborFromAPIStruct(a *api.Peer) (*config.Neighbor, error) {
|
||||
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
|
||||
pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl)
|
||||
}
|
||||
if a.TtlSecurity != nil {
|
||||
pconf.TtlSecurity.Config.Enabled = a.TtlSecurity.Enabled
|
||||
pconf.TtlSecurity.Config.TtlMin = uint8(a.TtlSecurity.TtlMin)
|
||||
}
|
||||
if a.State != nil {
|
||||
pconf.State.SessionState = config.SessionState(strings.ToUpper(string(a.State.SessionState)))
|
||||
pconf.State.AdminState = config.IntToAdminStateMap[int(a.State.AdminState)]
|
||||
@@ -771,6 +840,10 @@ func newPeerGroupFromAPIStruct(a *api.PeerGroup) (*config.PeerGroup, error) {
|
||||
pconf.EbgpMultihop.Config.Enabled = a.EbgpMultihop.Enabled
|
||||
pconf.EbgpMultihop.Config.MultihopTtl = uint8(a.EbgpMultihop.MultihopTtl)
|
||||
}
|
||||
if a.TtlSecurity != nil {
|
||||
pconf.TtlSecurity.Config.Enabled = a.TtlSecurity.Enabled
|
||||
pconf.TtlSecurity.Config.TtlMin = uint8(a.TtlSecurity.TtlMin)
|
||||
}
|
||||
if a.Info != nil {
|
||||
pconf.State.TotalPaths = a.Info.TotalPaths
|
||||
pconf.State.TotalPrefixes = a.Info.TotalPrefixes
|
||||
@@ -808,6 +881,10 @@ func (s *server) AddDynamicNeighbor(ctx context.Context, r *api.AddDynamicNeighb
|
||||
return &empty.Empty{}, s.bgpServer.AddDynamicNeighbor(ctx, r)
|
||||
}
|
||||
|
||||
func (s *server) DeleteDynamicNeighbor(ctx context.Context, r *api.DeleteDynamicNeighborRequest) (*empty.Empty, error) {
|
||||
return &empty.Empty{}, s.bgpServer.DeleteDynamicNeighbor(ctx, r)
|
||||
}
|
||||
|
||||
func newPrefixFromApiStruct(a *api.Prefix) (*table.Prefix, error) {
|
||||
_, prefix, err := net.ParseCIDR(a.IpPrefix)
|
||||
if err != nil {
|
||||
@@ -1135,6 +1212,11 @@ func toStatementApi(s *config.Statement) *api.Statement {
|
||||
Self: true,
|
||||
}
|
||||
}
|
||||
if string(s.Actions.BgpActions.SetNextHop) == "unchanged" {
|
||||
return &api.NexthopAction{
|
||||
Unchanged: true,
|
||||
}
|
||||
}
|
||||
return &api.NexthopAction{
|
||||
Address: string(s.Actions.BgpActions.SetNextHop),
|
||||
}
|
||||
@@ -1410,6 +1492,9 @@ func newNexthopActionFromApiStruct(a *api.NexthopAction) (*table.NexthopAction,
|
||||
if a.Self {
|
||||
return "self"
|
||||
}
|
||||
if a.Unchanged {
|
||||
return "unchanged"
|
||||
}
|
||||
return a.Address
|
||||
}(),
|
||||
))
|
||||
@@ -1757,3 +1842,7 @@ func (s *server) StopBgp(ctx context.Context, r *api.StopBgpRequest) (*empty.Emp
|
||||
func (s *server) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.GetTableResponse, error) {
|
||||
return s.bgpServer.GetTable(ctx, r)
|
||||
}
|
||||
|
||||
func (s *server) SetLogLevel(ctx context.Context, r *api.SetLogLevelRequest) (*empty.Empty, error) {
|
||||
return &empty.Empty{}, s.bgpServer.SetLogLevel(ctx, r)
|
||||
}
|
||||
|
||||
2
vendor/github.com/osrg/gobgp/pkg/server/mrt.go
generated
vendored
2
vendor/github.com/osrg/gobgp/pkg/server/mrt.go
generated
vendored
@@ -51,7 +51,7 @@ func (m *mrtWriter) loop() error {
|
||||
ops := []watchOption{}
|
||||
switch m.c.DumpType {
|
||||
case config.MRT_TYPE_UPDATES:
|
||||
ops = append(ops, watchUpdate(false))
|
||||
ops = append(ops, watchUpdate(false, ""))
|
||||
case config.MRT_TYPE_TABLE:
|
||||
if len(m.c.TableName) > 0 {
|
||||
ops = append(ops, watchTableName(m.c.TableName))
|
||||
|
||||
30
vendor/github.com/osrg/gobgp/pkg/server/peer.go
generated
vendored
30
vendor/github.com/osrg/gobgp/pkg/server/peer.go
generated
vendored
@@ -57,6 +57,10 @@ func (pg *peerGroup) AddDynamicNeighbor(c *config.DynamicNeighbor) {
|
||||
pg.dynamicNeighbors[c.Config.Prefix] = c
|
||||
}
|
||||
|
||||
func (pg *peerGroup) DeleteDynamicNeighbor(prefix string) {
|
||||
delete(pg.dynamicNeighbors, prefix)
|
||||
}
|
||||
|
||||
func newDynamicPeer(g *config.Global, neighborAddress string, pg *config.PeerGroup, loc *table.TableManager, policy *table.RoutingPolicy) *peer {
|
||||
conf := config.Neighbor{
|
||||
Config: config.NeighborConfig{
|
||||
@@ -131,6 +135,15 @@ func (peer *peer) ID() string {
|
||||
return peer.fsm.pConf.State.NeighborAddress
|
||||
}
|
||||
|
||||
func (peer *peer) RouterID() string {
|
||||
peer.fsm.lock.RLock()
|
||||
defer peer.fsm.lock.RUnlock()
|
||||
if peer.fsm.peerInfo.ID != nil {
|
||||
return peer.fsm.peerInfo.ID.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (peer *peer) TableID() string {
|
||||
return peer.tableId
|
||||
}
|
||||
@@ -348,7 +361,22 @@ func (peer *peer) stopPeerRestarting() {
|
||||
}
|
||||
|
||||
func (peer *peer) filterPathFromSourcePeer(path, old *table.Path) *table.Path {
|
||||
if peer.ID() != path.GetSource().Address.String() {
|
||||
// Consider 3 peers - A, B, C and prefix P originated by C. Parallel eBGP
|
||||
// sessions exist between A & B, and both have a single session with C.
|
||||
//
|
||||
// When A receives the withdraw from C, we enter this func for each peer of
|
||||
// A, with the following:
|
||||
// peer: [C, B #1, B #2]
|
||||
// path: new best for P facing B
|
||||
// old: old best for P facing C
|
||||
//
|
||||
// Our comparison between peer identifier and path source ID must be router
|
||||
// ID-based (not neighbor address), otherwise we will return early. If we
|
||||
// return early for one of the two sessions facing B
|
||||
// (whichever is not the new best path), we fail to send a withdraw towards
|
||||
// B, and the route is "stuck".
|
||||
// TODO: considerations for RFC6286
|
||||
if peer.RouterID() != path.GetSource().ID.String() {
|
||||
return path
|
||||
}
|
||||
|
||||
|
||||
415
vendor/github.com/osrg/gobgp/pkg/server/server.go
generated
vendored
415
vendor/github.com/osrg/gobgp/pkg/server/server.go
generated
vendored
@@ -23,6 +23,7 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/eapache/channels"
|
||||
@@ -52,35 +53,56 @@ func (l *tcpListener) Close() error {
|
||||
}
|
||||
|
||||
// avoid mapped IPv6 address
|
||||
func newTCPListener(address string, port uint32, ch chan *net.TCPConn) (*tcpListener, error) {
|
||||
func newTCPListener(address string, port uint32, bindToDev string, ch chan *net.TCPConn) (*tcpListener, error) {
|
||||
proto := "tcp4"
|
||||
family := syscall.AF_INET
|
||||
if ip := net.ParseIP(address); ip == nil {
|
||||
return nil, fmt.Errorf("can't listen on %s", address)
|
||||
} else if ip.To4() == nil {
|
||||
proto = "tcp6"
|
||||
family = syscall.AF_INET6
|
||||
}
|
||||
addr, err := net.ResolveTCPAddr(proto, net.JoinHostPort(address, strconv.Itoa(int(port))))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
addr := net.JoinHostPort(address, strconv.Itoa(int(port)))
|
||||
|
||||
var lc net.ListenConfig
|
||||
lc.Control = func(network, address string, c syscall.RawConn) error {
|
||||
if bindToDev != "" {
|
||||
err := setBindToDevSockopt(c, bindToDev)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Peer",
|
||||
"Key": addr,
|
||||
"BindToDev": bindToDev,
|
||||
}).Warnf("failed to bind Listener to device (%s): %s", bindToDev, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Note: Set TTL=255 for incoming connection listener in order to accept
|
||||
// connection in case for the neighbor has TTL Security settings.
|
||||
err := setsockoptIpTtl(c, family, 255)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Peer",
|
||||
"Key": addr,
|
||||
}).Warnf("cannot set TTL(=%d) for TCPListener: %s", 255, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
l, err := net.ListenTCP(proto, addr)
|
||||
l, err := lc.Listen(context.Background(), proto, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Note: Set TTL=255 for incoming connection listener in order to accept
|
||||
// connection in case for the neighbor has TTL Security settings.
|
||||
if err := setListenTCPTTLSockopt(l, 255); err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Peer",
|
||||
"Key": addr,
|
||||
}).Warnf("cannot set TTL(=%d) for TCPListener: %s", 255, err)
|
||||
listener, ok := l.(*net.TCPListener)
|
||||
if !ok {
|
||||
err = fmt.Errorf("unexpected connection listener (not for TCP)")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
closeCh := make(chan struct{})
|
||||
go func() error {
|
||||
for {
|
||||
conn, err := l.AcceptTCP()
|
||||
conn, err := listener.AcceptTCP()
|
||||
if err != nil {
|
||||
close(closeCh)
|
||||
log.WithFields(log.Fields{
|
||||
@@ -93,7 +115,7 @@ func newTCPListener(address string, port uint32, ch chan *net.TCPConn) (*tcpList
|
||||
}
|
||||
}()
|
||||
return &tcpListener{
|
||||
l: l,
|
||||
l: listener,
|
||||
ch: closeCh,
|
||||
}, nil
|
||||
}
|
||||
@@ -118,6 +140,7 @@ func GrpcOption(opt []grpc.ServerOption) ServerOption {
|
||||
}
|
||||
|
||||
type BgpServer struct {
|
||||
apiServer *server
|
||||
bgpConfig config.Bgp
|
||||
acceptCh chan *net.TCPConn
|
||||
incomings []*channels.InfiniteChannel
|
||||
@@ -158,9 +181,9 @@ func NewBgpServer(opt ...ServerOption) *BgpServer {
|
||||
s.mrtManager = newMrtManager(s)
|
||||
if len(opts.grpcAddress) != 0 {
|
||||
grpc.EnableTracing = false
|
||||
api := newAPIserver(s, grpc.NewServer(opts.grpcOption...), opts.grpcAddress)
|
||||
s.apiServer = newAPIserver(s, grpc.NewServer(opts.grpcOption...), opts.grpcAddress)
|
||||
go func() {
|
||||
if err := api.serve(); err != nil {
|
||||
if err := s.apiServer.serve(); err != nil {
|
||||
log.Fatalf("failed to listen grpc port: %s", err)
|
||||
}
|
||||
}()
|
||||
@@ -169,6 +192,14 @@ func NewBgpServer(opt ...ServerOption) *BgpServer {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *BgpServer) Stop() {
|
||||
s.StopBgp(context.Background(), &api.StopBgpRequest{})
|
||||
|
||||
if s.apiServer != nil {
|
||||
s.apiServer.grpcServer.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BgpServer) addIncoming(ch *channels.InfiniteChannel) {
|
||||
s.incomings = append(s.incomings, ch)
|
||||
}
|
||||
@@ -555,7 +586,7 @@ func filterpath(peer *peer, path, old *table.Path) *table.Path {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !peer.isRouteServerClient() && isASLoop(peer, path) {
|
||||
if !peer.isRouteServerClient() && isASLoop(peer, path) && !path.IsLocal() {
|
||||
return nil
|
||||
}
|
||||
return path
|
||||
@@ -853,8 +884,12 @@ func (s *BgpServer) notifyPostPolicyUpdateWatcher(peer *peer, pathList []*table.
|
||||
}
|
||||
|
||||
func newWatchEventPeerState(peer *peer, m *fsmMsg) *watchEventPeerState {
|
||||
_, rport := peer.fsm.RemoteHostPort()
|
||||
laddr, lport := peer.fsm.LocalHostPort()
|
||||
var laddr string
|
||||
var rport, lport uint16
|
||||
if peer.fsm.conn != nil {
|
||||
_, rport = peer.fsm.RemoteHostPort()
|
||||
laddr, lport = peer.fsm.LocalHostPort()
|
||||
}
|
||||
sentOpen := buildopen(peer.fsm.gConf, peer.fsm.pConf)
|
||||
peer.fsm.lock.RLock()
|
||||
recvOpen := peer.fsm.recvOpen
|
||||
@@ -1296,6 +1331,7 @@ func (s *BgpServer) deleteDynamicNeighbor(peer *peer, oldState bgp.FSMState, e *
|
||||
peer.fsm.lock.RUnlock()
|
||||
cleanInfiniteChannel(peer.fsm.outgoingCh)
|
||||
cleanInfiniteChannel(peer.fsm.incomingCh)
|
||||
s.delIncoming(peer.fsm.incomingCh)
|
||||
s.broadcastPeerState(peer, oldState, e)
|
||||
}
|
||||
|
||||
@@ -1696,6 +1732,9 @@ func (s *BgpServer) handleFSMMessage(peer *peer, e *fsmMsg) {
|
||||
}
|
||||
|
||||
func (s *BgpServer) EnableZebra(ctx context.Context, r *api.EnableZebraRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if s.zclient != nil {
|
||||
return fmt.Errorf("already connected to Zebra")
|
||||
@@ -1718,6 +1757,9 @@ func (s *BgpServer) EnableZebra(ctx context.Context, r *api.EnableZebraRequest)
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddBmp(ctx context.Context, r *api.AddBmpRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
_, ok := api.AddBmpRequest_MonitoringPolicy_name[int32(r.Policy)]
|
||||
if !ok {
|
||||
@@ -1735,6 +1777,9 @@ func (s *BgpServer) AddBmp(ctx context.Context, r *api.AddBmpRequest) error {
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeleteBmp(ctx context.Context, r *api.DeleteBmpRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.bmpManager.deleteServer(&config.BmpServerConfig{
|
||||
Address: r.Address,
|
||||
@@ -1744,6 +1789,9 @@ func (s *BgpServer) DeleteBmp(ctx context.Context, r *api.DeleteBmpRequest) erro
|
||||
}
|
||||
|
||||
func (s *BgpServer) StopBgp(ctx context.Context, r *api.StopBgpRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
s.mgmtOperation(func() error {
|
||||
names := make([]string, 0, len(s.neighborMap))
|
||||
for k := range s.neighborMap {
|
||||
@@ -1769,11 +1817,15 @@ func (s *BgpServer) StopBgp(ctx context.Context, r *api.StopBgpRequest) error {
|
||||
|
||||
if s.shutdownWG != nil {
|
||||
s.shutdownWG.Wait()
|
||||
s.shutdownWG = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BgpServer) SetPolicies(ctx context.Context, r *api.SetPoliciesRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
rp, err := newRoutingPolicyFromApiStruct(r)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1989,6 +2041,9 @@ func (s *BgpServer) addPathStream(vrfId string, pathList []*table.Path) error {
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.AddPathResponse, error) {
|
||||
if r == nil || r.Path == nil {
|
||||
return nil, fmt.Errorf("nil request")
|
||||
}
|
||||
var uuidBytes []byte
|
||||
err := s.mgmtOperation(func() error {
|
||||
path, err := api2Path(r.TableType, r.Path, false)
|
||||
@@ -2009,6 +2064,9 @@ func (s *BgpServer) AddPath(ctx context.Context, r *api.AddPathRequest) (*api.Ad
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeletePath(ctx context.Context, r *api.DeletePathRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
deletePathList := make([]*table.Path, 0)
|
||||
|
||||
@@ -2082,10 +2140,10 @@ func (s *BgpServer) updatePath(vrfId string, pathList []*table.Path) error {
|
||||
}
|
||||
|
||||
func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error {
|
||||
if r == nil || r.Global == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Global == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
g := r.Global
|
||||
if net.ParseIP(g.RouterId) == nil {
|
||||
return fmt.Errorf("invalid router-id format: %s", g.RouterId)
|
||||
@@ -2099,7 +2157,7 @@ func (s *BgpServer) StartBgp(ctx context.Context, r *api.StartBgpRequest) error
|
||||
if c.Config.Port > 0 {
|
||||
acceptCh := make(chan *net.TCPConn, 4096)
|
||||
for _, addr := range c.Config.LocalAddressList {
|
||||
l, err := newTCPListener(addr, uint32(c.Config.Port), acceptCh)
|
||||
l, err := newTCPListener(addr, uint32(c.Config.Port), g.BindToDevice, acceptCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2135,7 +2193,10 @@ func (s *BgpServer) listVrf() (l []*table.Vrf) {
|
||||
return l
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(*api.Vrf)) error {
|
||||
func (s *BgpServer) ListVrf(ctx context.Context, r *api.ListVrfRequest, fn func(*api.Vrf)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
toApi := func(v *table.Vrf) *api.Vrf {
|
||||
return &api.Vrf{
|
||||
Name: v.Name,
|
||||
@@ -2148,7 +2209,10 @@ func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(
|
||||
var l []*api.Vrf
|
||||
s.mgmtOperation(func() error {
|
||||
l = make([]*api.Vrf, 0, len(s.globalRib.Vrfs))
|
||||
for _, vrf := range s.globalRib.Vrfs {
|
||||
for name, vrf := range s.globalRib.Vrfs {
|
||||
if r.Name != "" && r.Name != name {
|
||||
continue
|
||||
}
|
||||
l = append(l, toApi(vrf.Clone()))
|
||||
}
|
||||
return nil
|
||||
@@ -2165,11 +2229,10 @@ func (s *BgpServer) ListVrf(ctx context.Context, _ *api.ListVrfRequest, fn func(
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error {
|
||||
if r == nil || r.Vrf == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Vrf == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
|
||||
name := r.Vrf.Name
|
||||
id := r.Vrf.Id
|
||||
|
||||
@@ -2206,10 +2269,10 @@ func (s *BgpServer) AddVrf(ctx context.Context, r *api.AddVrfRequest) error {
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeleteVrf(ctx context.Context, r *api.DeleteVrfRequest) error {
|
||||
if r == nil || r.Name == "" {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Name == "" {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
name := r.Name
|
||||
for _, n := range s.neighborMap {
|
||||
n.fsm.lock.RLock()
|
||||
@@ -2473,6 +2536,9 @@ func (s *BgpServer) getAdjRib(addr string, family bgp.RouteFamily, in bool, enab
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest, fn func(*api.Destination)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var tbl *table.Table
|
||||
var v map[*table.Path]*table.Validation
|
||||
var filtered map[string]*table.Path
|
||||
@@ -2520,7 +2586,7 @@ func (s *BgpServer) ListPath(ctx context.Context, r *api.ListPathRequest, fn fun
|
||||
}
|
||||
knownPathList := dst.GetAllKnownPathList()
|
||||
for i, path := range knownPathList {
|
||||
p := toPathApi(path, getValidation(v, path))
|
||||
p := toPathApi(path, getValidation(v, path), r.EnableNlriBinary, r.EnableAttributeBinary)
|
||||
if !table.SelectionOptions.DisableBestPathSelection {
|
||||
if i == 0 {
|
||||
switch r.TableType {
|
||||
@@ -2638,8 +2704,8 @@ func (s *BgpServer) getVrfRibInfo(name string, family bgp.RouteFamily) (info *ta
|
||||
}
|
||||
|
||||
func (s *BgpServer) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.GetTableResponse, error) {
|
||||
if r == nil {
|
||||
return nil, fmt.Errorf("invalid request")
|
||||
if r == nil || r.Family == nil {
|
||||
return nil, fmt.Errorf("nil request")
|
||||
}
|
||||
family := bgp.RouteFamily(0)
|
||||
if r.Family != nil {
|
||||
@@ -2674,6 +2740,9 @@ func (s *BgpServer) GetTable(ctx context.Context, r *api.GetTableRequest) (*api.
|
||||
}
|
||||
|
||||
func (s *BgpServer) GetBgp(ctx context.Context, r *api.GetBgpRequest) (*api.GetBgpResponse, error) {
|
||||
if r == nil {
|
||||
return nil, fmt.Errorf("nil request")
|
||||
}
|
||||
var rsp *api.GetBgpResponse
|
||||
s.mgmtOperation(func() error {
|
||||
g := s.bgpConfig.Global
|
||||
@@ -2691,7 +2760,72 @@ func (s *BgpServer) GetBgp(ctx context.Context, r *api.GetBgpRequest) (*api.GetB
|
||||
return rsp, nil
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListDynamicNeighbor(ctx context.Context, r *api.ListDynamicNeighborRequest, fn func(neighbor *api.DynamicNeighbor)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
toApi := func(dn *config.DynamicNeighbor) *api.DynamicNeighbor {
|
||||
return &api.DynamicNeighbor{
|
||||
Prefix: dn.Config.Prefix,
|
||||
PeerGroup: dn.Config.PeerGroup,
|
||||
}
|
||||
}
|
||||
var l []*api.DynamicNeighbor
|
||||
s.mgmtOperation(func() error {
|
||||
peerGroupName := r.PeerGroup
|
||||
for k, group := range s.peerGroupMap {
|
||||
if peerGroupName != "" && peerGroupName != k {
|
||||
continue
|
||||
}
|
||||
for _, dn := range group.dynamicNeighbors {
|
||||
l = append(l, toApi(dn))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}, false)
|
||||
for _, dn := range l {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
fn(dn)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListPeerGroup(ctx context.Context, r *api.ListPeerGroupRequest, fn func(*api.PeerGroup)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var l []*api.PeerGroup
|
||||
s.mgmtOperation(func() error {
|
||||
peerGroupName := r.PeerGroupName
|
||||
l = make([]*api.PeerGroup, 0, len(s.peerGroupMap))
|
||||
for k, group := range s.peerGroupMap {
|
||||
if peerGroupName != "" && peerGroupName != k {
|
||||
continue
|
||||
}
|
||||
pg := config.NewPeerGroupFromConfigStruct(group.Conf)
|
||||
l = append(l, pg)
|
||||
}
|
||||
return nil
|
||||
}, false)
|
||||
for _, pg := range l {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
fn(pg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListPeer(ctx context.Context, r *api.ListPeerRequest, fn func(*api.Peer)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var l []*api.Peer
|
||||
s.mgmtOperation(func() error {
|
||||
address := r.Address
|
||||
@@ -2839,6 +2973,9 @@ func (s *BgpServer) addNeighbor(c *config.Neighbor) error {
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddPeerGroup(ctx context.Context, r *api.AddPeerGroupRequest) error {
|
||||
if r == nil || r.PeerGroup == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
c, err := newPeerGroupFromAPIStruct(r.PeerGroup)
|
||||
if err != nil {
|
||||
@@ -2849,6 +2986,9 @@ func (s *BgpServer) AddPeerGroup(ctx context.Context, r *api.AddPeerGroupRequest
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddPeer(ctx context.Context, r *api.AddPeerRequest) error {
|
||||
if r == nil || r.Peer == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
c, err := newNeighborFromAPIStruct(r.Peer)
|
||||
if err != nil {
|
||||
@@ -2859,6 +2999,9 @@ func (s *BgpServer) AddPeer(ctx context.Context, r *api.AddPeerRequest) error {
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddDynamicNeighbor(ctx context.Context, r *api.AddDynamicNeighborRequest) error {
|
||||
if r == nil || r.DynamicNeighbor == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
c := &config.DynamicNeighbor{Config: config.DynamicNeighborConfig{
|
||||
Prefix: r.DynamicNeighbor.Prefix,
|
||||
@@ -2929,6 +3072,9 @@ func (s *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) erro
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeletePeerGroup(ctx context.Context, r *api.DeletePeerGroupRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
name := r.Name
|
||||
for _, n := range s.neighborMap {
|
||||
@@ -2944,6 +3090,9 @@ func (s *BgpServer) DeletePeerGroup(ctx context.Context, r *api.DeletePeerGroupR
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeletePeer(ctx context.Context, r *api.DeletePeerRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
c := &config.Neighbor{Config: config.NeighborConfig{
|
||||
NeighborAddress: r.Address,
|
||||
@@ -2953,6 +3102,16 @@ func (s *BgpServer) DeletePeer(ctx context.Context, r *api.DeletePeerRequest) er
|
||||
}, true)
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeleteDynamicNeighbor(ctx context.Context, r *api.DeleteDynamicNeighborRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
s.peerGroupMap[r.PeerGroup].DeleteDynamicNeighbor(r.Prefix)
|
||||
return nil
|
||||
}, true)
|
||||
}
|
||||
|
||||
func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) {
|
||||
name := pg.Config.PeerGroupName
|
||||
|
||||
@@ -2974,6 +3133,9 @@ func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool
|
||||
}
|
||||
|
||||
func (s *BgpServer) UpdatePeerGroup(ctx context.Context, r *api.UpdatePeerGroupRequest) (rsp *api.UpdatePeerGroupResponse, err error) {
|
||||
if r == nil || r.PeerGroup == nil {
|
||||
return nil, fmt.Errorf("nil request")
|
||||
}
|
||||
doSoftreset := false
|
||||
err = s.mgmtOperation(func() error {
|
||||
pg, err := newPeerGroupFromAPIStruct(r.PeerGroup)
|
||||
@@ -3081,6 +3243,9 @@ func (s *BgpServer) updateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, e
|
||||
}
|
||||
|
||||
func (s *BgpServer) UpdatePeer(ctx context.Context, r *api.UpdatePeerRequest) (rsp *api.UpdatePeerResponse, err error) {
|
||||
if r == nil || r.Peer == nil {
|
||||
return nil, fmt.Errorf("nil request")
|
||||
}
|
||||
doSoftReset := false
|
||||
err = s.mgmtOperation(func() error {
|
||||
c, err := newNeighborFromAPIStruct(r.Peer)
|
||||
@@ -3124,12 +3289,18 @@ func (s *BgpServer) sendNotification(op, addr string, subcode uint8, data []byte
|
||||
}
|
||||
|
||||
func (s *BgpServer) ShutdownPeer(ctx context.Context, r *api.ShutdownPeerRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.sendNotification("Neighbor shutdown", r.Address, bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN, newAdministrativeCommunication(r.Communication))
|
||||
}, true)
|
||||
}
|
||||
|
||||
func (s *BgpServer) ResetPeer(ctx context.Context, r *api.ResetPeerRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
addr := r.Address
|
||||
comm := r.Communication
|
||||
@@ -3197,18 +3368,27 @@ func (s *BgpServer) setAdminState(addr, communication string, enable bool) error
|
||||
}
|
||||
|
||||
func (s *BgpServer) EnablePeer(ctx context.Context, r *api.EnablePeerRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.setAdminState(r.Address, "", true)
|
||||
}, true)
|
||||
}
|
||||
|
||||
func (s *BgpServer) DisablePeer(ctx context.Context, r *api.DisablePeerRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.setAdminState(r.Address, r.Communication, false)
|
||||
}, true)
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListDefinedSet(ctx context.Context, r *api.ListDefinedSetRequest, fn func(*api.DefinedSet)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var cd *config.DefinedSets
|
||||
var err error
|
||||
err = s.mgmtOperation(func() error {
|
||||
@@ -3303,10 +3483,10 @@ func (s *BgpServer) ListDefinedSet(ctx context.Context, r *api.ListDefinedSetReq
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddDefinedSet(ctx context.Context, r *api.AddDefinedSetRequest) error {
|
||||
if r == nil || r.DefinedSet == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.DefinedSet == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
set, err := newDefinedSetFromApiStruct(r.DefinedSet)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3316,10 +3496,10 @@ func (s *BgpServer) AddDefinedSet(ctx context.Context, r *api.AddDefinedSetReque
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeleteDefinedSet(ctx context.Context, r *api.DeleteDefinedSetRequest) error {
|
||||
if r == nil || r.DefinedSet == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.DefinedSet == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
set, err := newDefinedSetFromApiStruct(r.DefinedSet)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3329,6 +3509,9 @@ func (s *BgpServer) DeleteDefinedSet(ctx context.Context, r *api.DeleteDefinedSe
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListStatement(ctx context.Context, r *api.ListStatementRequest, fn func(*api.Statement)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var l []*api.Statement
|
||||
s.mgmtOperation(func() error {
|
||||
s := s.policy.GetStatement(r.Name)
|
||||
@@ -3350,10 +3533,10 @@ func (s *BgpServer) ListStatement(ctx context.Context, r *api.ListStatementReque
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddStatement(ctx context.Context, r *api.AddStatementRequest) error {
|
||||
if r == nil || r.Statement == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Statement == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
st, err := newStatementFromApiStruct(r.Statement)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3363,10 +3546,10 @@ func (s *BgpServer) AddStatement(ctx context.Context, r *api.AddStatementRequest
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeleteStatement(ctx context.Context, r *api.DeleteStatementRequest) error {
|
||||
if r == nil || r.Statement == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Statement == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
st, err := newStatementFromApiStruct(r.Statement)
|
||||
if err == nil {
|
||||
err = s.policy.DeleteStatement(st, r.All)
|
||||
@@ -3376,6 +3559,9 @@ func (s *BgpServer) DeleteStatement(ctx context.Context, r *api.DeleteStatementR
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListPolicy(ctx context.Context, r *api.ListPolicyRequest, fn func(*api.Policy)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var l []*api.Policy
|
||||
s.mgmtOperation(func() error {
|
||||
pl := s.policy.GetPolicy(r.Name)
|
||||
@@ -3397,10 +3583,10 @@ func (s *BgpServer) ListPolicy(ctx context.Context, r *api.ListPolicyRequest, fn
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddPolicy(ctx context.Context, r *api.AddPolicyRequest) error {
|
||||
if r == nil || r.Policy == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Policy == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
p, err := newPolicyFromApiStruct(r.Policy)
|
||||
if err == nil {
|
||||
err = s.policy.AddPolicy(p, r.ReferExistingStatements)
|
||||
@@ -3410,10 +3596,10 @@ func (s *BgpServer) AddPolicy(ctx context.Context, r *api.AddPolicyRequest) erro
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeletePolicy(ctx context.Context, r *api.DeletePolicyRequest) error {
|
||||
if r == nil || r.Policy == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Policy == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
p, err := newPolicyFromApiStruct(r.Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3456,12 +3642,11 @@ func (s *BgpServer) toPolicyInfo(name string, dir api.PolicyDirection) (string,
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyAssignmentRequest, fn func(*api.PolicyAssignment)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var a []*api.PolicyAssignment
|
||||
err := s.mgmtOperation(func() error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(s.neighborMap)+1)
|
||||
if r.Name == "" {
|
||||
names = append(names, table.GLOBAL_RIB_NAME)
|
||||
@@ -3491,9 +3676,6 @@ func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyA
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(policies) == 0 {
|
||||
continue
|
||||
}
|
||||
t := &table.PolicyAssignment{
|
||||
Name: name,
|
||||
Type: dir,
|
||||
@@ -3519,10 +3701,10 @@ func (s *BgpServer) ListPolicyAssignment(ctx context.Context, r *api.ListPolicyA
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddPolicyAssignment(ctx context.Context, r *api.AddPolicyAssignmentRequest) error {
|
||||
if r == nil || r.Assignment == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Assignment == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
id, dir, err := s.toPolicyInfo(r.Assignment.Name, r.Assignment.Direction)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3532,10 +3714,10 @@ func (s *BgpServer) AddPolicyAssignment(ctx context.Context, r *api.AddPolicyAss
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeletePolicyAssignment(ctx context.Context, r *api.DeletePolicyAssignmentRequest) error {
|
||||
if r == nil || r.Assignment == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Assignment == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
id, dir, err := s.toPolicyInfo(r.Assignment.Name, r.Assignment.Direction)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3545,10 +3727,10 @@ func (s *BgpServer) DeletePolicyAssignment(ctx context.Context, r *api.DeletePol
|
||||
}
|
||||
|
||||
func (s *BgpServer) SetPolicyAssignment(ctx context.Context, r *api.SetPolicyAssignmentRequest) error {
|
||||
if r == nil || r.Assignment == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r == nil || r.Assignment == nil {
|
||||
return fmt.Errorf("invalid request")
|
||||
}
|
||||
id, dir, err := s.toPolicyInfo(r.Assignment.Name, r.Assignment.Direction)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -3558,6 +3740,9 @@ func (s *BgpServer) SetPolicyAssignment(ctx context.Context, r *api.SetPolicyAss
|
||||
}
|
||||
|
||||
func (s *BgpServer) EnableMrt(ctx context.Context, r *api.EnableMrtRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.mrtManager.enable(&config.MrtConfig{
|
||||
DumpInterval: r.DumpInterval,
|
||||
@@ -3569,12 +3754,18 @@ func (s *BgpServer) EnableMrt(ctx context.Context, r *api.EnableMrtRequest) erro
|
||||
}
|
||||
|
||||
func (s *BgpServer) DisableMrt(ctx context.Context, r *api.DisableMrtRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.mrtManager.disable(&config.MrtConfig{})
|
||||
}, false)
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListRpki(ctx context.Context, r *api.ListRpkiRequest, fn func(*api.Rpki)) error {
|
||||
if r == nil || r.Family == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var l []*api.Rpki
|
||||
err := s.mgmtOperation(func() error {
|
||||
for _, r := range s.roaManager.GetServers() {
|
||||
@@ -3623,6 +3814,9 @@ func (s *BgpServer) ListRpki(ctx context.Context, r *api.ListRpkiRequest, fn fun
|
||||
}
|
||||
|
||||
func (s *BgpServer) ListRpkiTable(ctx context.Context, r *api.ListRpkiTableRequest, fn func(*api.Roa)) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
var l []*api.Roa
|
||||
err := s.mgmtOperation(func() error {
|
||||
family := bgp.RouteFamily(0)
|
||||
@@ -3649,30 +3843,45 @@ func (s *BgpServer) ListRpkiTable(ctx context.Context, r *api.ListRpkiTableReque
|
||||
}
|
||||
|
||||
func (s *BgpServer) AddRpki(ctx context.Context, r *api.AddRpkiRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.roaManager.AddServer(net.JoinHostPort(r.Address, strconv.Itoa(int(r.Port))), r.Lifetime)
|
||||
}, false)
|
||||
}
|
||||
|
||||
func (s *BgpServer) DeleteRpki(ctx context.Context, r *api.DeleteRpkiRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.roaManager.DeleteServer(r.Address)
|
||||
}, false)
|
||||
}
|
||||
|
||||
func (s *BgpServer) EnableRpki(ctx context.Context, r *api.EnableRpkiRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.roaManager.Enable(r.Address)
|
||||
}, false)
|
||||
}
|
||||
|
||||
func (s *BgpServer) DisableRpki(ctx context.Context, r *api.DisableRpkiRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
return s.roaManager.Disable(r.Address)
|
||||
}, false)
|
||||
}
|
||||
|
||||
func (s *BgpServer) ResetRpki(ctx context.Context, r *api.ResetRpkiRequest) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("nil request")
|
||||
}
|
||||
return s.mgmtOperation(func() error {
|
||||
if r.Soft {
|
||||
return s.roaManager.SoftReset(r.Address)
|
||||
@@ -3691,9 +3900,9 @@ func (s *BgpServer) MonitorTable(ctx context.Context, r *api.MonitorTableRequest
|
||||
return s.watch(watchBestPath(r.Current)), nil
|
||||
case api.TableType_ADJ_IN:
|
||||
if r.PostPolicy {
|
||||
return s.watch(watchPostUpdate(r.Current)), nil
|
||||
return s.watch(watchPostUpdate(r.Current, r.Name)), nil
|
||||
}
|
||||
return s.watch(watchUpdate(r.Current)), nil
|
||||
return s.watch(watchUpdate(r.Current, r.Name)), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported resource type: %v", r.TableType)
|
||||
}
|
||||
@@ -3733,11 +3942,14 @@ func (s *BgpServer) MonitorTable(ctx context.Context, r *api.MonitorTableRequest
|
||||
if path == nil || (r.Family != nil && family != path.GetRouteFamily()) {
|
||||
continue
|
||||
}
|
||||
if len(r.Name) > 0 && r.Name != path.GetSource().Address.String() {
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
fn(toPathApi(path, nil))
|
||||
fn(toPathApi(path, nil, false, false))
|
||||
}
|
||||
}
|
||||
case <-ctx.Done():
|
||||
@@ -3754,7 +3966,13 @@ func (s *BgpServer) MonitorPeer(ctx context.Context, r *api.MonitorPeerRequest,
|
||||
}
|
||||
|
||||
go func() {
|
||||
w := s.watch(watchPeerState(r.Current))
|
||||
// So that both flags are not required, assume that if the
|
||||
// initial_state flag is true, then the caller desires that the initial
|
||||
// state be returned whether or not it is established and regardless of
|
||||
// the value of `current`.
|
||||
current := r.Current || r.InitialState
|
||||
nonEstablished := r.InitialState
|
||||
w := s.watch(watchPeerState(current, nonEstablished))
|
||||
defer func() {
|
||||
w.Stop()
|
||||
}()
|
||||
@@ -3795,6 +4013,22 @@ func (s *BgpServer) MonitorPeer(ctx context.Context, r *api.MonitorPeerRequest,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *BgpServer) SetLogLevel(ctx context.Context, r *api.SetLogLevelRequest) error {
|
||||
prevLevel := log.GetLevel()
|
||||
newLevel := log.Level(r.Level)
|
||||
if prevLevel == newLevel {
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Infof("Logging level unchanged -- level already set to %v", newLevel)
|
||||
} else {
|
||||
log.SetLevel(newLevel)
|
||||
log.WithFields(log.Fields{
|
||||
"Topic": "Config",
|
||||
}).Infof("Logging level changed -- prev: %v, new: %v", prevLevel, newLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type watchEventType string
|
||||
|
||||
const (
|
||||
@@ -3879,8 +4113,10 @@ type watchOptions struct {
|
||||
initUpdate bool
|
||||
initPostUpdate bool
|
||||
initPeerState bool
|
||||
nonEstablished bool
|
||||
tableName string
|
||||
recvMessage bool
|
||||
peerAddress string
|
||||
}
|
||||
|
||||
type watchOption func(*watchOptions)
|
||||
@@ -3894,29 +4130,34 @@ func watchBestPath(current bool) watchOption {
|
||||
}
|
||||
}
|
||||
|
||||
func watchUpdate(current bool) watchOption {
|
||||
func watchUpdate(current bool, peerAddress string) watchOption {
|
||||
return func(o *watchOptions) {
|
||||
o.preUpdate = true
|
||||
if current {
|
||||
o.initUpdate = true
|
||||
}
|
||||
o.peerAddress = peerAddress
|
||||
}
|
||||
}
|
||||
|
||||
func watchPostUpdate(current bool) watchOption {
|
||||
func watchPostUpdate(current bool, peerAddress string) watchOption {
|
||||
return func(o *watchOptions) {
|
||||
o.postUpdate = true
|
||||
if current {
|
||||
o.initPostUpdate = true
|
||||
}
|
||||
o.peerAddress = peerAddress
|
||||
}
|
||||
}
|
||||
|
||||
func watchPeerState(current bool) watchOption {
|
||||
func watchPeerState(current, includeNonEstablished bool) watchOption {
|
||||
return func(o *watchOptions) {
|
||||
o.peerState = true
|
||||
if current {
|
||||
o.initPeerState = true
|
||||
if includeNonEstablished {
|
||||
o.nonEstablished = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4071,11 +4312,13 @@ func (s *BgpServer) watch(opts ...watchOption) (w *watcher) {
|
||||
}
|
||||
if w.opts.initPeerState {
|
||||
for _, peer := range s.neighborMap {
|
||||
peer.fsm.lock.RLock()
|
||||
notEstablished := peer.fsm.state != bgp.BGP_FSM_ESTABLISHED
|
||||
peer.fsm.lock.RUnlock()
|
||||
if notEstablished {
|
||||
continue
|
||||
if !w.opts.nonEstablished {
|
||||
peer.fsm.lock.RLock()
|
||||
notEstablished := peer.fsm.state != bgp.BGP_FSM_ESTABLISHED
|
||||
peer.fsm.lock.RUnlock()
|
||||
if notEstablished {
|
||||
continue
|
||||
}
|
||||
}
|
||||
w.notify(newWatchEventPeerState(peer, nil))
|
||||
}
|
||||
@@ -4090,10 +4333,14 @@ func (s *BgpServer) watch(opts ...watchOption) (w *watcher) {
|
||||
for _, peer := range s.neighborMap {
|
||||
peer.fsm.lock.RLock()
|
||||
notEstablished := peer.fsm.state != bgp.BGP_FSM_ESTABLISHED
|
||||
peerAddress := peer.fsm.peerInfo.Address.String()
|
||||
peer.fsm.lock.RUnlock()
|
||||
if notEstablished {
|
||||
continue
|
||||
}
|
||||
if len(w.opts.peerAddress) > 0 && w.opts.peerAddress != peerAddress {
|
||||
continue
|
||||
}
|
||||
configNeighbor := w.s.toConfig(peer, false)
|
||||
for _, rf := range peer.configuredRFlist() {
|
||||
peer.fsm.lock.RLock()
|
||||
@@ -4148,9 +4395,13 @@ func (s *BgpServer) watch(opts ...watchOption) (w *watcher) {
|
||||
for peerInfo, paths := range pathsByPeer {
|
||||
// create copy which can be access to without mutex
|
||||
var configNeighbor *config.Neighbor
|
||||
if peer, ok := s.neighborMap[peerInfo.Address.String()]; ok {
|
||||
peerAddress := peerInfo.Address.String()
|
||||
if peer, ok := s.neighborMap[peerAddress]; ok {
|
||||
configNeighbor = w.s.toConfig(peer, false)
|
||||
}
|
||||
if w.opts.peerAddress != "" && w.opts.peerAddress != peerAddress {
|
||||
continue
|
||||
}
|
||||
|
||||
w.notify(&watchEventUpdate{
|
||||
PeerAS: peerInfo.AS,
|
||||
|
||||
9
vendor/github.com/osrg/gobgp/pkg/server/sockopt.go
generated
vendored
9
vendor/github.com/osrg/gobgp/pkg/server/sockopt.go
generated
vendored
@@ -17,6 +17,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"syscall"
|
||||
|
||||
@@ -27,10 +28,6 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
||||
return setTcpMD5SigSockopt(l, address, key)
|
||||
}
|
||||
|
||||
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||
return setListenTcpTTLSockopt(l, ttl)
|
||||
}
|
||||
|
||||
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
return setTcpTTLSockopt(conn, ttl)
|
||||
}
|
||||
@@ -39,6 +36,10 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
return setTcpMinTTLSockopt(conn, ttl)
|
||||
}
|
||||
|
||||
func setBindToDevSockopt(sc syscall.RawConn, device string) error {
|
||||
return fmt.Errorf("binding connection to a device is not supported")
|
||||
}
|
||||
|
||||
func dialerControl(network, address string, c syscall.RawConn, ttl, ttlMin uint8, password string, bindInterface string) error {
|
||||
if password != "" {
|
||||
log.WithFields(log.Fields{
|
||||
|
||||
9
vendor/github.com/osrg/gobgp/pkg/server/sockopt_bsd.go
generated
vendored
9
vendor/github.com/osrg/gobgp/pkg/server/sockopt_bsd.go
generated
vendored
@@ -35,15 +35,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
||||
return setsockOptInt(sc, syscall.IPPROTO_TCP, tcpMD5SIG, 1)
|
||||
}
|
||||
|
||||
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||
family := extractFamilyFromTCPListener(l)
|
||||
sc, err := l.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setsockoptIpTtl(sc, family, ttl)
|
||||
}
|
||||
|
||||
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
family := extractFamilyFromTCPConn(conn)
|
||||
sc, err := conn.SyscallConn()
|
||||
|
||||
9
vendor/github.com/osrg/gobgp/pkg/server/sockopt_darwin.go
generated
vendored
9
vendor/github.com/osrg/gobgp/pkg/server/sockopt_darwin.go
generated
vendored
@@ -27,15 +27,6 @@ func setTcpMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
||||
return fmt.Errorf("setting md5 is not supported")
|
||||
}
|
||||
|
||||
func setListenTcpTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||
family := extractFamilyFromTCPListener(l)
|
||||
sc, err := l.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setsockoptIpTtl(sc, family, ttl)
|
||||
}
|
||||
|
||||
func setTcpTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
family := syscall.AF_INET
|
||||
if strings.Contains(conn.RemoteAddr().String(), "[") {
|
||||
|
||||
16
vendor/github.com/osrg/gobgp/pkg/server/sockopt_linux.go
generated
vendored
16
vendor/github.com/osrg/gobgp/pkg/server/sockopt_linux.go
generated
vendored
@@ -70,13 +70,8 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
||||
return setsockOptString(sc, syscall.IPPROTO_TCP, tcpMD5SIG, string(b[:]))
|
||||
}
|
||||
|
||||
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||
family := extractFamilyFromTCPListener(l)
|
||||
sc, err := l.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setsockoptIpTtl(sc, family, ttl)
|
||||
func setBindToDevSockopt(sc syscall.RawConn, device string) error {
|
||||
return setsockOptString(sc, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, device)
|
||||
}
|
||||
|
||||
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
@@ -162,14 +157,9 @@ func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8
|
||||
}
|
||||
}
|
||||
if bindInterface != "" {
|
||||
if err := c.Control(func(fd uintptr) {
|
||||
sockerr = os.NewSyscallError("setsockopt", syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, bindInterface))
|
||||
}); err != nil {
|
||||
if err := setBindToDevSockopt(c, bindInterface); err != nil {
|
||||
return err
|
||||
}
|
||||
if sockerr != nil {
|
||||
return sockerr
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
13
vendor/github.com/osrg/gobgp/pkg/server/sockopt_openbsd.go
generated
vendored
13
vendor/github.com/osrg/gobgp/pkg/server/sockopt_openbsd.go
generated
vendored
@@ -370,15 +370,6 @@ func setTCPMD5SigSockopt(l *net.TCPListener, address string, key string) error {
|
||||
return setsockoptTcpMD5Sig(sc, address, key)
|
||||
}
|
||||
|
||||
func setListenTCPTTLSockopt(l *net.TCPListener, ttl int) error {
|
||||
family := extractFamilyFromTCPListener(l)
|
||||
sc, err := l.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return setsockoptIpTtl(sc, family, ttl)
|
||||
}
|
||||
|
||||
func setTCPTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
family := extractFamilyFromTCPConn(conn)
|
||||
sc, err := conn.SyscallConn()
|
||||
@@ -403,6 +394,10 @@ func setTCPMinTTLSockopt(conn *net.TCPConn, ttl int) error {
|
||||
return setsockOptInt(sc, level, name, ttl)
|
||||
}
|
||||
|
||||
func setBindToDevSockopt(sc syscall.RawConn, device string) error {
|
||||
return fmt.Errorf("binding connection to a device is not supported")
|
||||
}
|
||||
|
||||
func dialerControl(network, address string, c syscall.RawConn, ttl, minTtl uint8, password string, bindInterface string) error {
|
||||
if password != "" {
|
||||
log.WithFields(log.Fields{
|
||||
|
||||
12
vendor/github.com/osrg/gobgp/pkg/server/util.go
generated
vendored
12
vendor/github.com/osrg/gobgp/pkg/server/util.go
generated
vendored
@@ -59,20 +59,12 @@ func decodeAdministrativeCommunication(data []byte) (string, []byte) {
|
||||
if communicationLen > bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX {
|
||||
communicationLen = bgp.BGP_ERROR_ADMINISTRATIVE_COMMUNICATION_MAX
|
||||
}
|
||||
if communicationLen > len(data)+1 {
|
||||
communicationLen = len(data) + 1
|
||||
if communicationLen > len(data)-1 {
|
||||
communicationLen = len(data) - 1
|
||||
}
|
||||
return string(data[1 : communicationLen+1]), data[communicationLen+1:]
|
||||
}
|
||||
|
||||
func extractFamilyFromTCPListener(l *net.TCPListener) int {
|
||||
family := syscall.AF_INET
|
||||
if strings.Contains(l.Addr().String(), "[") {
|
||||
family = syscall.AF_INET6
|
||||
}
|
||||
return family
|
||||
}
|
||||
|
||||
func extractFamilyFromTCPConn(conn *net.TCPConn) int {
|
||||
family := syscall.AF_INET
|
||||
if strings.Contains(conn.RemoteAddr().String(), "[") {
|
||||
|
||||
2
vendor/github.com/osrg/gobgp/pkg/server/zclient.go
generated
vendored
2
vendor/github.com/osrg/gobgp/pkg/server/zclient.go
generated
vendored
@@ -364,7 +364,7 @@ func (z *zebraClient) updatePathByNexthopCache(paths []*table.Path) {
|
||||
func (z *zebraClient) loop() {
|
||||
w := z.server.watch([]watchOption{
|
||||
watchBestPath(true),
|
||||
watchPostUpdate(true),
|
||||
watchPostUpdate(true, ""),
|
||||
}...)
|
||||
defer w.Stop()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user