diff options
-rw-r--r-- | packet/bgp/bgp.go | 10 | ||||
-rw-r--r-- | server/fsm.go | 26 | ||||
-rw-r--r-- | table/message.go | 53 |
3 files changed, 74 insertions, 15 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index 8a793720..9d6678d3 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -4439,7 +4439,7 @@ func NewPathAttributeAtomicAggregate() *PathAttributeAtomicAggregate { type PathAttributeAggregatorParam struct { AS uint32 - askind reflect.Kind + Askind reflect.Kind Address net.IP } @@ -4461,18 +4461,18 @@ func (p *PathAttributeAggregator) DecodeFromBytes(data []byte) error { if len(p.PathAttribute.Value) == 6 { p.Value.AS = uint32(binary.BigEndian.Uint16(p.PathAttribute.Value[0:2])) p.Value.Address = p.PathAttribute.Value[2:] - p.Value.askind = reflect.Uint16 + p.Value.Askind = reflect.Uint16 } else { p.Value.AS = binary.BigEndian.Uint32(p.PathAttribute.Value[0:4]) p.Value.Address = p.PathAttribute.Value[4:] - p.Value.askind = reflect.Uint32 + p.Value.Askind = reflect.Uint32 } return nil } func (p *PathAttributeAggregator) Serialize() ([]byte, error) { var buf []byte - switch p.Value.askind { + switch p.Value.Askind { case reflect.Uint16: buf = make([]byte, 6) binary.BigEndian.PutUint16(buf, uint16(p.Value.AS)) @@ -4513,7 +4513,7 @@ func NewPathAttributeAggregator(as interface{}, address string) *PathAttributeAg }, Value: PathAttributeAggregatorParam{ AS: uint32(v.Uint()), - askind: v.Kind(), + Askind: v.Kind(), Address: net.ParseIP(address).To4(), }, } diff --git a/server/fsm.go b/server/fsm.go index e0fb53c2..e80c6512 100644 --- a/server/fsm.go +++ b/server/fsm.go @@ -634,18 +634,23 @@ func (h *FSMHandler) recvMessageWithError() (*FsmMsg, error) { } else { // FIXME: we should use the original message for bmp/mrt table.UpdatePathAttrs4ByteAs(body) - fmsg.PathList = table.ProcessMessage(m, h.fsm.peerInfo, fmsg.timestamp) - id := h.fsm.pConf.Config.NeighborAddress - policyMutex.RLock() - for _, path := range fmsg.PathList { - if path.IsEOR() { - continue - } - if h.fsm.policy.ApplyPolicy(id, table.POLICY_DIRECTION_IN, path, nil) == nil { - path.Filter(id, table.POLICY_DIRECTION_IN) + err := table.UpdatePathAggregator4ByteAs(body) + if err == nil { + fmsg.PathList = table.ProcessMessage(m, h.fsm.peerInfo, fmsg.timestamp) + id := h.fsm.pConf.Config.NeighborAddress + policyMutex.RLock() + for _, path := range fmsg.PathList { + if path.IsEOR() { + continue + } + if h.fsm.policy.ApplyPolicy(id, table.POLICY_DIRECTION_IN, path, nil) == nil { + path.Filter(id, table.POLICY_DIRECTION_IN) + } } + policyMutex.RUnlock() + } else { + fmsg.MsgData = err } - policyMutex.RUnlock() } fmsg.payload = make([]byte, len(headerBuf)+len(bodyBuf)) copy(fmsg.payload, headerBuf) @@ -1009,6 +1014,7 @@ func (h *FSMHandler) sendMessageloop() error { "Data": m, }).Debug("update for 2byte AS peer") table.UpdatePathAttrs2ByteAs(m.Body.(*bgp.BGPUpdate)) + table.UpdatePathAggregator2ByteAs(m.Body.(*bgp.BGPUpdate)) } b, err := m.Serialize() if err != nil { diff --git a/table/message.go b/table/message.go index 5cf9b5b6..68801e73 100644 --- a/table/message.go +++ b/table/message.go @@ -20,6 +20,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/osrg/gobgp/packet/bgp" "hash/fnv" + "reflect" ) func UpdatePathAttrs2ByteAs(msg *bgp.BGPUpdate) error { @@ -198,6 +199,58 @@ func UpdatePathAttrs4ByteAs(msg *bgp.BGPUpdate) error { return nil } +func UpdatePathAggregator2ByteAs(msg *bgp.BGPUpdate) { + as := uint32(0) + var addr string + for _, attr := range msg.PathAttributes { + switch attr.(type) { + case *bgp.PathAttributeAggregator: + agg := attr.(*bgp.PathAttributeAggregator) + agg.Value.Askind = reflect.Uint16 + if agg.Value.AS > (1<<16)-1 { + as = agg.Value.AS + addr = agg.Value.Address.String() + agg.Value.AS = bgp.AS_TRANS + } + } + } + if as != 0 { + msg.PathAttributes = append(msg.PathAttributes, bgp.NewPathAttributeAs4Aggregator(as, addr)) + } +} + +func UpdatePathAggregator4ByteAs(msg *bgp.BGPUpdate) error { + var aggAttr *bgp.PathAttributeAggregator + var agg4Attr *bgp.PathAttributeAs4Aggregator + agg4AttrPos := 0 + for i, attr := range msg.PathAttributes { + switch attr.(type) { + case *bgp.PathAttributeAggregator: + attr := attr.(*bgp.PathAttributeAggregator) + if attr.Value.Askind == reflect.Uint16 { + aggAttr = attr + aggAttr.Value.Askind = reflect.Uint32 + } + case *bgp.PathAttributeAs4Aggregator: + agg4Attr = attr.(*bgp.PathAttributeAs4Aggregator) + agg4AttrPos = i + } + } + if aggAttr == nil && agg4Attr == nil { + return nil + } + + if aggAttr == nil && agg4Attr != nil { + return bgp.NewMessageError(bgp.BGP_ERROR_UPDATE_MESSAGE_ERROR, bgp.BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "AS4 AGGREGATOR attribute exists, but AGGREGATOR doesn't") + } + + if agg4Attr != nil { + msg.PathAttributes = append(msg.PathAttributes[:agg4AttrPos], msg.PathAttributes[agg4AttrPos+1:]...) + aggAttr.Value.AS = agg4Attr.Value.AS + } + return nil +} + func createUpdateMsgFromPath(path *Path, msg *bgp.BGPMessage) *bgp.BGPMessage { rf := path.GetRouteFamily() |