From 7284d4cf8b3f9ecd03068dfa3ab3d433860b5089 Mon Sep 17 00:00:00 2001 From: Hitoshi Irino Date: Sun, 21 Jul 2019 15:08:23 +0900 Subject: [PATCH] Avoid panic by receiving vpnv6 prefixes with zebra reported in issue #2113 - Additionally bug fix which avoid panic caused by displaying vpnv6 prefixes using gobgp vrf rib - Supporting FRRouting 7.1.x --- cmd/gobgp/neighbor.go | 3 +- docs/sources/zebra.md | 22 +++---- internal/pkg/config/default.go | 2 +- internal/pkg/zebra/zapi.go | 101 +++++++++++++++++--------------- internal/pkg/zebra/zapi_test.go | 60 +++++++++---------- pkg/server/zclient.go | 14 ++++- 6 files changed, 111 insertions(+), 91 deletions(-) diff --git a/cmd/gobgp/neighbor.go b/cmd/gobgp/neighbor.go index 2a1075da7..ef8e904b4 100644 --- a/cmd/gobgp/neighbor.go +++ b/cmd/gobgp/neighbor.go @@ -925,7 +925,8 @@ func showNeighborRib(r string, name string, args []string) error { for _, dst := range rib { prefix := dst.Prefix if t == api.TableType_VRF { - s := strings.Split(prefix, ":") + // extract prefix from original which is RD(AS:VRF):IPv4 or IPv6 address + s := strings.SplitN(prefix, ":", 3) prefix = s[len(s)-1] } _, p, _ := net.ParseCIDR(prefix) diff --git a/docs/sources/zebra.md b/docs/sources/zebra.md index e79a8c97f..d8b5f595b 100644 --- a/docs/sources/zebra.md +++ b/docs/sources/zebra.md @@ -15,11 +15,11 @@ version 4), 5.0.x (Zebra API version 5), and 7.0.x (Zebra API version 6) are supported as default. FRRouting version 5.0.x changes zebra message and it doesn't keep backward compatibility for FRRouting version 4.0.x although FRRouting version 4.0.x and 5.0.x use Zebra API -version 5. Also, FRRouting version 7.0.x changes zebra message and it -doesn't keep backward compatibility for FRRouting version 6.0.x -although FRRouting version 6.0.x and 7.0.x use Zebra API version 6. If -you need to integrate with FRRouting version 4.0.x or 6.0x, please use -`software-name` configuration. +version 5. Also, FRRouting version 7.0.x and 7.1.x changes zebra +message and it doesn't keep backward compatibility for FRRouting +version 6.0.x although FRRouting version 6.0.x, 7.0.x and 7.1.x use +Zebra API version 6. If you need to integrate with FRRouting version +4.0.x or 6.0x, please use `software-name` configuration. ## Contents @@ -59,15 +59,17 @@ You need to enable the zebra feature in the Global configuration as follows. For connecting to FRRouting 7.0.x, please specify `6`. - `mpls-label-range-size` specifies mpls label range size for - requesting to Zebra. It works with FRRouting 5.0.x, FRRouting - 6.0.x and FRRouting 7.0.x. + requesting to Zebra. It works with FRRouting 5.0.x, FRRouting 6.0.x, + FRRouting 7.0.x and FRRouting 7.1.x. - `sotware-name` specifies software name for zebra when only `version` configuration cannot specify software uniquely. This configuration is used with 'version' configuration. For connecting to FRRouting - 6.0.x, please specify `6` as `version` and `frr6` as - `software-name`. For connecting to FRRouting 4.0.x, please specify - `5` as `version` and `frr4` as `software-name`. + 7.1.x, please specify `6` as `version` and `frr7.1` as + `software-name`. For connecting to FRRouting 6.0.x, please specify + `6` as `version` and `frr6` as `software-name`. For connecting to + FRRouting 4.0.x, please specify `5` as `version` and `frr4` as + `software-name`. ## Check Routes from zebra diff --git a/internal/pkg/config/default.go b/internal/pkg/config/default.go index 7fd5b5c1b..3ac8db34f 100644 --- a/internal/pkg/config/default.go +++ b/internal/pkg/config/default.go @@ -422,7 +422,7 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { } //SoftwareName for Zebra - allowableZebraSoftwareName := []string{"", "quagga", "frr3", "frr4", "frr5", "frr6", "frr7"} + allowableZebraSoftwareName := []string{"", "quagga", "frr3", "frr4", "frr5", "frr6", "frr7", "frr7.1"} isAllowable := false for _, allowable := range allowableZebraSoftwareName { if b.Zebra.Config.SoftwareName == allowable { diff --git a/internal/pkg/zebra/zapi.go b/internal/pkg/zebra/zapi.go index 7bd1ea39c..fd308a6d3 100644 --- a/internal/pkg/zebra/zapi.go +++ b/internal/pkg/zebra/zapi.go @@ -1060,10 +1060,11 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software version = MaxZapiVer } isAllowableSoftware := true + if ((version == 2 || version == 3) && software != "" && software != "quagga") || (version == 4 && software != "" && software != "frr3") || (version == 5 && software != "" && software != "frr4" && software != "frr5") || - (version == 6 && software != "" && software != "frr6" && software != "frr7") { + (version == 6 && software != "" && software != "frr6" && software != "frr7" && software != "frr7.1") { isAllowableSoftware = false } if !isAllowableSoftware { @@ -1086,7 +1087,7 @@ func NewClient(network, address string, typ ROUTE_TYPE, version uint8, software for { m, more := <-outgoing if more { - b, err := m.Serialize() + b, err := m.Serialize(software) if err != nil { log.WithFields(log.Fields{ "Topic": "Zebra", @@ -1575,8 +1576,8 @@ func (h *Header) DecodeFromBytes(data []byte) error { } type Body interface { - DecodeFromBytes([]byte, uint8) error - Serialize(uint8) ([]byte, error) + DecodeFromBytes([]byte, uint8, string) error + Serialize(uint8, string) ([]byte, error) String(uint8, string) string } @@ -1584,12 +1585,12 @@ type UnknownBody struct { Data []byte } -func (b *UnknownBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *UnknownBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { b.Data = data return nil } -func (b *UnknownBody) Serialize(version uint8) ([]byte, error) { +func (b *UnknownBody) Serialize(version uint8, softwareName string) ([]byte, error) { return b.Data, nil } @@ -1606,7 +1607,7 @@ type HelloBody struct { // Reference: zread_hello function in zebra/zserv.c of Quagga1.2.x (ZAPI3) // Reference: zread_hello function in zebra/zserv.c of FRR3.x (ZAPI4) // Reference: zread_hello function in zebra/zapi_msg.c of FRR5.x (ZAPI5) -func (b *HelloBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *HelloBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { b.RedistDefault = ROUTE_TYPE(data[0]) if version >= 4 { b.Instance = binary.BigEndian.Uint16(data[1:3]) @@ -1620,7 +1621,7 @@ func (b *HelloBody) DecodeFromBytes(data []byte, version uint8) error { // Reference: zebra_hello_send function in lib/zclient.c of Quagga1.2.x (ZAPI3) // Reference: zebra_hello_send function in lib/zclient.c of FRR3.x (ZAPI4) // Reference: zebra_hello_send function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *HelloBody) Serialize(version uint8) ([]byte, error) { +func (b *HelloBody) Serialize(version uint8, softwareName string) ([]byte, error) { if version <= 3 { return []byte{uint8(b.RedistDefault)}, nil } else { // version >= 4 @@ -1654,7 +1655,7 @@ type RedistributeBody struct { // Reference: zebra_redistribute_add function in zebra/redistribute.c of Quagga1.2.x (ZAPI3) // Reference: zebra_redistribute_add function in zebra/redistribute.c of FRR3.x (ZAPI4) // Reference: zebra_redistribute_add function in zebra/redistribute.c of FRR5.x (ZAPI5) -func (b *RedistributeBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *RedistributeBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { if version <= 3 { b.Redist = ROUTE_TYPE(data[0]) } else { // version >= 4 @@ -1668,7 +1669,7 @@ func (b *RedistributeBody) DecodeFromBytes(data []byte, version uint8) error { // Reference: zebra_redistribute_send function in lib/zclient.c of Quagga1.2.x (ZAPI3) // Reference: zebra_redistribute_send function in lib/zclient.c of FRR3.x (ZAPI4) // Reference: zebra_redistribute_send function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *RedistributeBody) Serialize(version uint8) ([]byte, error) { +func (b *RedistributeBody) Serialize(version uint8, softwareName string) ([]byte, error) { if version <= 3 { return []byte{uint8(b.Redist)}, nil } else { // version >= 4 @@ -1726,7 +1727,7 @@ type InterfaceUpdateBody struct { // Reference: zebra_interface_if_set_value function in lib/zclient.c of Quagga1.2.x (ZAPI4) // Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR3.x (ZAPI4) // Reference: zebra_interface_if_set_value function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { if len(data) < INTERFACE_NAMSIZ+33 { return fmt.Errorf("lack of bytes. need %d but %d", INTERFACE_NAMSIZ+29, len(data)) } @@ -1791,7 +1792,7 @@ func (b *InterfaceUpdateBody) DecodeFromBytes(data []byte, version uint8) error return nil } -func (b *InterfaceUpdateBody) Serialize(version uint8) ([]byte, error) { +func (b *InterfaceUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { return []byte{}, nil } @@ -1816,7 +1817,7 @@ type InterfaceAddressUpdateBody struct { // Reference: zebra_interface_address_read function in lib/zclient.c of Quagga1.2.x (ZAPI4) // Reference: zebra_interface_address_read function in lib/zclient.c of FRR3.x (ZAPI4) // Reference: zebra_interface_address_read function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *InterfaceAddressUpdateBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *InterfaceAddressUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { b.Index = binary.BigEndian.Uint32(data[:4]) b.Flags = INTERFACE_ADDRESS_FLAG(data[4]) family := data[5] @@ -1830,7 +1831,7 @@ func (b *InterfaceAddressUpdateBody) DecodeFromBytes(data []byte, version uint8) return nil } -func (b *InterfaceAddressUpdateBody) Serialize(version uint8) ([]byte, error) { +func (b *InterfaceAddressUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { return []byte{}, nil } @@ -1848,7 +1849,7 @@ type RouterIDUpdateBody struct { // Reference: zebra_router_id_update_read function in lib/zclient.c of Quagga1.2.x (ZAPI4) // Reference: zebra_router_id_update_read function in lib/zclient.c of FRR3.x (ZAPI4) // Reference: zebra_router_id_update_read function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *RouterIDUpdateBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *RouterIDUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { family := data[0] addrlen, err := addressByteLength(family) @@ -1860,7 +1861,7 @@ func (b *RouterIDUpdateBody) DecodeFromBytes(data []byte, version uint8) error { return nil } -func (b *RouterIDUpdateBody) Serialize(version uint8) ([]byte, error) { +func (b *RouterIDUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { return []byte{}, nil } @@ -1879,6 +1880,7 @@ type Nexthop struct { BlackholeType uint8 LabelNum uint8 MplsLabels []uint32 + Onlink uint8 } func (n *Nexthop) String() string { @@ -2038,7 +2040,7 @@ func (b *IPRouteBody) IsWithdraw(version uint8) bool { // Reference: zapi_ipv4_route function in lib/zclient.c of Quagga1.2.x (ZAPI3) // Reference: zapi_ipv4_route function in lib/zclient.c of FRR3.x (ZAPI4) // Reference: zapi_route_encode function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) { +func (b *IPRouteBody) Serialize(version uint8, softwareName string) ([]byte, error) { var buf []byte if version <= 3 { buf = make([]byte, 5) @@ -2137,6 +2139,9 @@ func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) { buf = append(buf, uint8(nexthop.Type)) + if version == 6 && softwareName == "frr7.1" { + buf = append(buf, nexthop.Onlink) + } if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4) || (version >= 4 && nexthop.Type == FRR_NEXTHOP_TYPE_IPV4) { buf = append(buf, nexthop.Gate.To4()...) @@ -2207,7 +2212,7 @@ func (b *IPRouteBody) Serialize(version uint8) ([]byte, error) { // Reference: zebra_read_ipv4 function in bgpd/bgp_zebra.c of Quagga1.2.x (ZAPI3) // Reference: zebra_read_ipv4 function in bgpd/bgp_zebra.c of FRR4.x (ZAPI4) // Reference: zapi_route_decode function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { if b == nil { return fmt.Errorf("IPRouteBody is nil") } @@ -2321,6 +2326,10 @@ func (b *IPRouteBody) DecodeFromBytes(data []byte, version uint8) error { nexthop.VrfId = binary.BigEndian.Uint32(data[pos : pos+4]) nexthop.Type = NEXTHOP_TYPE(data[pos+4]) pos += 5 + if softwareName == "frr7.1" { + nexthop.Onlink = uint8(data[pos]) + pos += 1 + } } if (version <= 3 && nexthop.Type == NEXTHOP_TYPE_IPV4) || @@ -2531,7 +2540,7 @@ type NexthopLookupBody struct { } // Quagga only. Reference: zread_ipv[4|6]_nexthop_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *NexthopLookupBody) Serialize(version uint8) ([]byte, error) { +func (b *NexthopLookupBody) Serialize(version uint8, softwareName string) ([]byte, error) { family := addressFamilyFromApi(b.Api, version) buf := make([]byte, 0) @@ -2544,7 +2553,7 @@ func (b *NexthopLookupBody) Serialize(version uint8) ([]byte, error) { } // Quagga only. Reference: zsend_ipv[4|6]_nexthop_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *NexthopLookupBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *NexthopLookupBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { family := addressFamilyFromApi(b.Api, version) addrByteLen, err := addressByteLength(family) if err != nil { @@ -2601,7 +2610,7 @@ type ImportLookupBody struct { } // Quagga only. Reference: zread_ipv4_import_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *ImportLookupBody) Serialize(version uint8) ([]byte, error) { +func (b *ImportLookupBody) Serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 1) buf[0] = b.PrefixLength buf = append(buf, b.Addr.To4()...) @@ -2609,7 +2618,7 @@ func (b *ImportLookupBody) Serialize(version uint8) ([]byte, error) { } // Quagga only. Reference: zsend_ipv4_import_lookup in zebra/zserv.c of Quagga1.2.x (ZAPI3) -func (b *ImportLookupBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *ImportLookupBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { family := addressFamilyFromApi(b.Api, version) addrByteLen, err := addressByteLength(family) if err != nil { @@ -2704,7 +2713,7 @@ func (n *RegisteredNexthop) Serialize() ([]byte, error) { // Reference: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) // Reference: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) // Reference: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) -func (n *RegisteredNexthop) DecodeFromBytes(data []byte) error { +func (n *RegisteredNexthop) DecodeFromBytes(data []byte, softwareName string) error { // Connected (1 byte) n.Connected = uint8(data[0]) // Address Family (2 bytes) @@ -2731,7 +2740,7 @@ type NexthopRegisterBody struct { // Reference: sendmsg_nexthop in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) // Reference: sendmsg_zebra_rnh in bgpd/bgp_nht.c of FRR3.x (ZAPI4) // Reference: zclient_send_rnh function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *NexthopRegisterBody) Serialize(version uint8) ([]byte, error) { +func (b *NexthopRegisterBody) Serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 0) // List of Registered Nexthops @@ -2749,14 +2758,14 @@ func (b *NexthopRegisterBody) Serialize(version uint8) ([]byte, error) { // Reference: zserv_nexthop_register in zebra/zserv.c of Quagga1.2.x (ZAPI3) // Reference: zserv_rnh_register in zebra/zserv.c of FRR3.x (ZAPI4) // Reference: zread_rnh_register in zebra/zapi_msg.c of FRR5.x (ZAPI5) -func (b *NexthopRegisterBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *NexthopRegisterBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { offset := 0 // List of Registered Nexthops b.Nexthops = []*RegisteredNexthop{} for len(data[offset:]) > 0 { nh := new(RegisteredNexthop) - err := nh.DecodeFromBytes(data[offset:]) + err := nh.DecodeFromBytes(data[offset:], softwareName) if err != nil { return err } @@ -2786,7 +2795,7 @@ type NexthopUpdateBody IPRouteBody // Reference: send_client function in zebra/zebra_rnh.c of Quagga1.2.x (ZAPI3) // Reference: send_client function in zebra/zebra_rnh.c of FRR3.x (ZAPI4) // Reference: send_client function in zebra/zebra_rnh.c of FRR5.x (ZAPI5) -func (b *NexthopUpdateBody) Serialize(version uint8) ([]byte, error) { +func (b *NexthopUpdateBody) Serialize(version uint8, softwareName string) ([]byte, error) { // Address Family (2 bytes) buf := make([]byte, 3) binary.BigEndian.PutUint16(buf, uint16(b.Prefix.Family)) @@ -2831,7 +2840,7 @@ func (b *NexthopUpdateBody) Serialize(version uint8) ([]byte, error) { // Reference: bgp_parse_nexthop_update function in bgpd/bgp_nht.c of Quagga1.2.x (ZAPI3) // Reference: bgp_parse_nexthop_update function in bgpd/bgp_nht.c of FRR3.x (ZAPI4) // Reference: zapi_nexthop_update_decode function in lib/zclient.c of FRR5.x (ZAPI5) -func (b *NexthopUpdateBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *NexthopUpdateBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { // Address Family (2 bytes) prefixFamily := binary.BigEndian.Uint16(data[0:2]) b.Prefix.Family = uint8(prefixFamily) @@ -2892,14 +2901,14 @@ type LabelManagerConnectBody struct { } // Reference: lm_label_manager_connect in lib/zclient.c of FRR -func (b *LabelManagerConnectBody) Serialize(version uint8) ([]byte, error) { +func (b *LabelManagerConnectBody) Serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 3) buf[0] = uint8(b.RedistDefault) binary.BigEndian.PutUint16(buf[1:3], b.Instance) return buf, nil } -func (b *LabelManagerConnectBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *LabelManagerConnectBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { size := 1 // FRR v4 may work incorrectly. It returns result only although it uses ZAPI v5. if version >= 4 { @@ -2938,7 +2947,7 @@ type GetLabelChunkBody struct { // Reference: zread_get_label_chunk in zebra/zserv.c of FRR3.x // Reference: zread_get_label_chunk in zebra/zapi_msg.c of FRR5.x and 6.x -func (b *GetLabelChunkBody) Serialize(version uint8) ([]byte, error) { +func (b *GetLabelChunkBody) Serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 8) pos := 0 if version > 4 { @@ -2954,7 +2963,7 @@ func (b *GetLabelChunkBody) Serialize(version uint8) ([]byte, error) { // Reference: zsend_assign_label_chunk_response in zebra/zserv.c of FRR3.x // Reference: zsend_assign_label_chunk_response in zebra/zapi_msg.c of FRR5.x and 6.x -func (b *GetLabelChunkBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *GetLabelChunkBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { size := 9 if version > 4 { size = 12 @@ -2987,7 +2996,7 @@ type ReleaseLabelChunkBody struct { End uint32 } -func (b *ReleaseLabelChunkBody) Serialize(version uint8) ([]byte, error) { +func (b *ReleaseLabelChunkBody) Serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 11) pos := 0 if version > 4 { @@ -3001,7 +3010,7 @@ func (b *ReleaseLabelChunkBody) Serialize(version uint8) ([]byte, error) { return buf[0:pos], nil } -func (b *ReleaseLabelChunkBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *ReleaseLabelChunkBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { // No response from Zebra return nil } @@ -3031,7 +3040,7 @@ type VrfLabelBody struct { } // Reference: zclient_send_vrf_label in lib/zclient.c of FRR 5.x and 6.x -func (b *VrfLabelBody) Serialize(version uint8) ([]byte, error) { +func (b *VrfLabelBody) Serialize(version uint8, softwareName string) ([]byte, error) { buf := make([]byte, 6) binary.BigEndian.PutUint32(buf[0:4], b.Label) buf[4] = uint8(b.Afi) @@ -3039,7 +3048,7 @@ func (b *VrfLabelBody) Serialize(version uint8) ([]byte, error) { return buf, nil } -func (b *VrfLabelBody) DecodeFromBytes(data []byte, version uint8) error { +func (b *VrfLabelBody) DecodeFromBytes(data []byte, version uint8, softwareName string) error { if len(data) < 6 { return fmt.Errorf("invalid message length for VRF_LABEL message: %d<6", len(data)) } @@ -3060,11 +3069,11 @@ type Message struct { Body Body } -func (m *Message) Serialize() ([]byte, error) { +func (m *Message) Serialize(software string) ([]byte, error) { var body []byte if m.Body != nil { var err error - body, err = m.Body.Serialize(m.Header.Version) + body, err = m.Body.Serialize(m.Header.Version, software) if err != nil { return nil, err } @@ -3077,7 +3086,7 @@ func (m *Message) Serialize() ([]byte, error) { return append(hdr, body...), nil } -func (m *Message) parseMessage(data []byte) error { +func (m *Message) parseMessage(data []byte, software string) error { switch m.Header.Command { case INTERFACE_ADD, INTERFACE_DELETE, INTERFACE_UP, INTERFACE_DOWN: m.Body = &InterfaceUpdateBody{} @@ -3096,10 +3105,10 @@ func (m *Message) parseMessage(data []byte) error { default: m.Body = &UnknownBody{} } - return m.Body.DecodeFromBytes(data, m.Header.Version) + return m.Body.DecodeFromBytes(data, m.Header.Version, software) } -func (m *Message) parseFrrMessage(data []byte) error { +func (m *Message) parseFrrMessage(data []byte, software string) error { switch m.Header.Command { case FRR_INTERFACE_ADD, FRR_INTERFACE_DELETE, FRR_INTERFACE_UP, FRR_INTERFACE_DOWN: m.Body = &InterfaceUpdateBody{} @@ -3144,7 +3153,7 @@ func (m *Message) parseFrrMessage(data []byte) error { default: m.Body = &UnknownBody{} } - return m.Body.DecodeFromBytes(data, m.Header.Version) + return m.Body.DecodeFromBytes(data, m.Header.Version, software) } func (m *Message) parseFrrZapi5Message(data []byte, software string) error { @@ -3202,7 +3211,7 @@ func (m *Message) parseFrrZapi5Message(data []byte, software string) error { default: m.Body = &UnknownBody{} } - return m.Body.DecodeFromBytes(data, m.Header.Version) + return m.Body.DecodeFromBytes(data, m.Header.Version, software) } func (m *Message) parseFrrZapi6Message(data []byte, software string) error { @@ -3259,19 +3268,19 @@ func (m *Message) parseFrrZapi6Message(data []byte, software string) error { default: m.Body = &UnknownBody{} } - return m.Body.DecodeFromBytes(data, m.Header.Version) + return m.Body.DecodeFromBytes(data, m.Header.Version, software) } func ParseMessage(hdr *Header, data []byte, software string) (m *Message, err error) { m = &Message{Header: *hdr} if m.Header.Version == 4 { - err = m.parseFrrMessage(data) + err = m.parseFrrMessage(data, software) } else if m.Header.Version == 5 { err = m.parseFrrZapi5Message(data, software) } else if m.Header.Version == 6 { err = m.parseFrrZapi6Message(data, software) } else { - err = m.parseMessage(data) + err = m.parseMessage(data, software) } if err != nil { return nil, err diff --git a/internal/pkg/zebra/zapi_test.go b/internal/pkg/zebra/zapi_test.go index 9454a8a08..b75421c2b 100644 --- a/internal/pkg/zebra/zapi_test.go +++ b/internal/pkg/zebra/zapi_test.go @@ -127,12 +127,12 @@ func Test_InterfaceUpdateBody(t *testing.T) { pos += 1 } b := &InterfaceUpdateBody{} - err := b.DecodeFromBytes(buf, v) + err := b.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) assert.Equal("01:23:45:67:89:ab", b.HardwareAddr.String()) buf = make([]byte, INTERFACE_NAMSIZ+32) //size mismatch b = &InterfaceUpdateBody{} - err = b.DecodeFromBytes(buf, v) + err = b.DecodeFromBytes(buf, v, "") assert.NotEqual(nil, err) } } @@ -159,7 +159,7 @@ func Test_InterfaceAddressUpdateBody(t *testing.T) { copy(buf[pos:pos+4], []byte(dst)) b := &InterfaceAddressUpdateBody{} - err := b.DecodeFromBytes(buf, v) + err := b.DecodeFromBytes(buf, v, "") require.NoError(t, err) assert.Equal(uint32(0), b.Index) @@ -172,7 +172,7 @@ func Test_InterfaceAddressUpdateBody(t *testing.T) { buf[5] = 0x4 pos += 1 b = &InterfaceAddressUpdateBody{} - err = b.DecodeFromBytes(buf, v) + err = b.DecodeFromBytes(buf, v, "") assert.NotEqual(nil, err) } } @@ -192,7 +192,7 @@ func Test_RouterIDUpdateBody(t *testing.T) { buf[pos] = byte(32) b := &RouterIDUpdateBody{} - err := b.DecodeFromBytes(buf, v) + err := b.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) assert.Equal("192.168.100.1", b.Prefix.String()) assert.Equal(uint8(32), b.Length) @@ -201,7 +201,7 @@ func Test_RouterIDUpdateBody(t *testing.T) { buf[0] = 0x4 pos += 1 b = &RouterIDUpdateBody{} - err = b.DecodeFromBytes(buf, v) + err = b.DecodeFromBytes(buf, v, "") assert.NotEqual(nil, err) } } @@ -294,7 +294,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 1) // mtu pos += 4 r := &IPRouteBody{Api: command[v]} - err := r.DecodeFromBytes(buf, v) + err := r.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) assert.Equal("192.168.100.0", r.Prefix.Prefix.String()) assert.Equal(uint8(0x18), r.Prefix.PrefixLen) @@ -311,7 +311,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { assert.Equal(uint32(1), r.Mtu) //Serialize - buf, err = r.Serialize(v) + buf, err = r.Serialize(v, "") assert.Equal(nil, err) switch v { case 2, 3: @@ -416,7 +416,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { pos += 4 r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v) + err = r.DecodeFromBytes(buf, v, "") switch v { case 2, 3, 4: assert.Equal("MESSAGE_METRIC message length invalid pos:14 rest:14", err.Error()) @@ -461,7 +461,7 @@ func Test_IPRouteBody_IPv4(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 0) //metric pos += 4 r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v) + err = r.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) } } @@ -560,7 +560,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 1) // mtu pos += 4 r := &IPRouteBody{Api: command[v]} - err := r.DecodeFromBytes(buf, v) + err := r.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) assert.Equal("2001:db8:0:f101::", r.Prefix.Prefix.String()) assert.Equal(uint8(64), r.Prefix.PrefixLen) @@ -577,7 +577,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) { assert.Equal(uint32(1), r.Mtu) //Serialize - buf, err = r.Serialize(v) + buf, err = r.Serialize(v, "") assert.Equal(nil, err) switch v { case 2, 3: @@ -683,7 +683,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) { pos += 4 r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v) + err = r.DecodeFromBytes(buf, v, "") switch v { case 2, 3, 4: assert.Equal("message length invalid pos:39 rest:46", err.Error()) @@ -726,7 +726,7 @@ func Test_IPRouteBody_IPv6(t *testing.T) { buf[pos] = 1 //distance binary.BigEndian.PutUint32(buf[pos:], 0) //metic r = &IPRouteBody{Api: command[v]} - err = r.DecodeFromBytes(buf, v) + err = r.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) } } @@ -754,7 +754,7 @@ func Test_NexthopLookupBody(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 3) b := &NexthopLookupBody{Api: IPV4_NEXTHOP_LOOKUP} - err := b.DecodeFromBytes(buf, 2) + err := b.DecodeFromBytes(buf, 2, "") assert.Equal(nil, err) assert.Equal("192.168.50.0", b.Addr.String()) assert.Equal(uint32(10), b.Metric) @@ -763,7 +763,7 @@ func Test_NexthopLookupBody(t *testing.T) { assert.Equal("172.16.1.101", b.Nexthops[0].Gate.String()) //Serialize - buf, err = b.Serialize(2) + buf, err = b.Serialize(2, "") ip = net.ParseIP("192.168.50.0").To4() assert.Equal(nil, err) assert.Equal([]byte(ip)[0:4], buf[0:4]) @@ -771,7 +771,7 @@ func Test_NexthopLookupBody(t *testing.T) { // length invalid buf = make([]byte, 3) b = &NexthopLookupBody{Api: IPV4_NEXTHOP_LOOKUP} - err = b.DecodeFromBytes(buf, 2) + err = b.DecodeFromBytes(buf, 2, "") assert.NotEqual(nil, err) //ipv6 @@ -793,7 +793,7 @@ func Test_NexthopLookupBody(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 3) b = &NexthopLookupBody{Api: IPV6_NEXTHOP_LOOKUP} - err = b.DecodeFromBytes(buf, 2) + err = b.DecodeFromBytes(buf, 2, "") assert.Equal(nil, err) assert.Equal("2001:db8:0:f101::", b.Addr.String()) assert.Equal(uint32(10), b.Metric) @@ -802,7 +802,7 @@ func Test_NexthopLookupBody(t *testing.T) { assert.Equal("2001:db8:0:1111::1", b.Nexthops[0].Gate.String()) //Serialize - buf, err = b.Serialize(2) + buf, err = b.Serialize(2, "") ip = net.ParseIP("2001:db8:0:f101::").To16() assert.Equal(nil, err) assert.Equal([]byte(ip)[0:16], buf[0:16]) @@ -810,7 +810,7 @@ func Test_NexthopLookupBody(t *testing.T) { // length invalid buf = make([]byte, 15) b = &NexthopLookupBody{Api: IPV6_NEXTHOP_LOOKUP} - err = b.DecodeFromBytes(buf, 2) + err = b.DecodeFromBytes(buf, 2, "") assert.NotEqual(nil, err) } @@ -836,7 +836,7 @@ func Test_ImportLookupBody(t *testing.T) { binary.BigEndian.PutUint32(buf[pos:], 3) b := &ImportLookupBody{Api: IPV4_IMPORT_LOOKUP} - err := b.DecodeFromBytes(buf, 2) + err := b.DecodeFromBytes(buf, 2, "") assert.Equal(nil, err) assert.Equal("192.168.50.0", b.Addr.String()) assert.Equal(uint32(10), b.Metric) @@ -846,7 +846,7 @@ func Test_ImportLookupBody(t *testing.T) { //Serialize b.PrefixLength = uint8(24) - buf, err = b.Serialize(2) + buf, err = b.Serialize(2, "") ip = net.ParseIP("192.168.50.0").To4() assert.Equal(nil, err) assert.Equal(uint8(24), buf[0]) @@ -855,7 +855,7 @@ func Test_ImportLookupBody(t *testing.T) { // length invalid buf = make([]byte, 3) b = &ImportLookupBody{Api: IPV4_IMPORT_LOOKUP} - err = b.DecodeFromBytes(buf, 2) + err = b.DecodeFromBytes(buf, 2, "") assert.NotEqual(nil, err) } @@ -882,7 +882,7 @@ func Test_NexthopRegisterBody(t *testing.T) { for v := MinZapiVer; v <= MaxZapiVer; v++ { // Test DecodeFromBytes() b := &NexthopRegisterBody{Api: command[v]} - err := b.DecodeFromBytes(bufIn, v) + err := b.DecodeFromBytes(bufIn, v, "") assert.Nil(err) // Test decoded values @@ -894,7 +894,7 @@ func Test_NexthopRegisterBody(t *testing.T) { assert.Equal(net.ParseIP("2001:db8:1:1::1").To16(), b.Nexthops[1].Prefix) // Test Serialize() - bufOut, err := b.Serialize(v) + bufOut, err := b.Serialize(v, "") assert.Nil(err) // Test serialised value @@ -950,7 +950,7 @@ func Test_NexthopUpdateBody(t *testing.T) { // Test DecodeFromBytes() b := &NexthopUpdateBody{Api: command[v]} - err := b.DecodeFromBytes(bufIn, v) + err := b.DecodeFromBytes(bufIn, v, "") assert.Nil(err) // Test decoded values @@ -982,12 +982,12 @@ func Test_GetLabelChunkBody(t *testing.T) { binary.BigEndian.PutUint32(buf[8:], 89) //End b := &GetLabelChunkBody{} - err := b.DecodeFromBytes(buf, v) + err := b.DecodeFromBytes(buf, v, "") assert.Equal(nil, err) //Serialize b.ChunkSize = 10 - buf, err = b.Serialize(v) + buf, err = b.Serialize(v, "") assert.Equal(nil, err) assert.Equal(byte(routeType[v]), buf[0]) bi := make([]byte, 4) @@ -1006,11 +1006,11 @@ func Test_VrfLabelBody(t *testing.T) { bufIn[4] = byte(AFI_IP) bufIn[5] = byte(LSP_BGP) b := &VrfLabelBody{} - err := b.DecodeFromBytes(bufIn, v) + err := b.DecodeFromBytes(bufIn, v, "") assert.Equal(nil, err) //Serialize var bufOut []byte - bufOut, err = b.Serialize(v) + bufOut, err = b.Serialize(v, "") assert.Equal(nil, err) assert.Equal(bufIn, bufOut) } diff --git a/pkg/server/zclient.go b/pkg/server/zclient.go index 6bfdc8951..1c315a6ca 100644 --- a/pkg/server/zclient.go +++ b/pkg/server/zclient.go @@ -121,9 +121,17 @@ func addMessageLabelToIPRouteBody(path *table.Path, vrfId uint32, z *zebraClient rf := path.GetRouteFamily() if v > 4 && (rf == bgp.RF_IPv4_VPN || rf == bgp.RF_IPv6_VPN) { *msgFlags |= zebra.FRR_ZAPI5_MESSAGE_LABEL - for _, label := range path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).Labels.Labels { - nexthop.LabelNum++ - nexthop.MplsLabels = append(nexthop.MplsLabels, label) + switch rf { + case bgp.RF_IPv4_VPN: + for _, label := range path.GetNlri().(*bgp.LabeledVPNIPAddrPrefix).Labels.Labels { + nexthop.LabelNum++ + nexthop.MplsLabels = append(nexthop.MplsLabels, label) + } + case bgp.RF_IPv6_VPN: + for _, label := range path.GetNlri().(*bgp.LabeledVPNIPv6AddrPrefix).Labels.Labels { + nexthop.LabelNum++ + nexthop.MplsLabels = append(nexthop.MplsLabels, label) + } } } }