Ref: zebra_read_ipv4 in bgpd/bgp_zebra.c of Quagga1.2.x&FRR3.x(ZAPI3&4) Ref: zapi_route_decode in lib/zclient.c of FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6)
(data []byte, version uint8, software Software)
| 2863 | // Ref: zebra_read_ipv4 in bgpd/bgp_zebra.c of Quagga1.2.x&FRR3.x(ZAPI3&4) |
| 2864 | // Ref: zapi_route_decode in lib/zclient.c of FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) |
| 2865 | func (b *IPRouteBody) decodeFromBytes(data []byte, version uint8, software Software) error { |
| 2866 | if b == nil { |
| 2867 | return fmt.Errorf("IPRouteBody is nil") |
| 2868 | } |
| 2869 | if len(data) < 1 { |
| 2870 | return errors.New("IPRouteBody data length is too short") |
| 2871 | } |
| 2872 | // frr: STREAM_GETC(s, api->type); |
| 2873 | b.Type = RouteType(data[0]) |
| 2874 | if b.Type > getRouteAll(version, software) { // ver5 and later work, fix for older |
| 2875 | return fmt.Errorf("unknown route type: %d in version: %d (%s)", b.Type, version, software.string()) |
| 2876 | } |
| 2877 | |
| 2878 | if version <= 3 { |
| 2879 | if len(data) < 2 { |
| 2880 | return errors.New("IPRouteBody data length is too short") |
| 2881 | } |
| 2882 | b.Flags = Flag(data[1]) |
| 2883 | data = data[2:] |
| 2884 | } else { // version >= 4 |
| 2885 | if len(data) < 7 { |
| 2886 | return errors.New("IPRouteBody data length is too short") |
| 2887 | } |
| 2888 | // frr: STREAM_GETW(s, api->instance); |
| 2889 | b.instance = binary.BigEndian.Uint16(data[1:3]) |
| 2890 | // frr: STREAM_GETL(s, api->flags); |
| 2891 | b.Flags = Flag(binary.BigEndian.Uint32(data[3:7])) |
| 2892 | data = data[7:] |
| 2893 | } |
| 2894 | if version == 6 && software.name == "frr" && software.version >= 7.5 { |
| 2895 | if len(data) < 4 { |
| 2896 | return errors.New("IPRouteBody data length is too short") |
| 2897 | } |
| 2898 | // frr7.5: STREAM_GETL(s, api->message); |
| 2899 | b.Message = MessageFlag(binary.BigEndian.Uint32(data[:4])) |
| 2900 | data = data[4:] |
| 2901 | } else { |
| 2902 | if len(data) < 1 { |
| 2903 | return errors.New("IPRouteBody data length is too short") |
| 2904 | } |
| 2905 | b.Message = MessageFlag(data[0]) // frr: STREAM_GETC(s, api->message); |
| 2906 | data = data[1:] |
| 2907 | } |
| 2908 | b.Safi = SafiUnicast |
| 2909 | b.Prefix.Family = b.API.addressFamily(version) // return AF_UNSPEC if version > 4 |
| 2910 | var evpnNexthop Nexthop |
| 2911 | if version > 4 { |
| 2912 | if len(data) < 1 { |
| 2913 | return errors.New("IPRouteBody safi type data length is too short") |
| 2914 | } |
| 2915 | b.Safi = Safi(data[0]) // frr: STREAM_GETC(s, api->safi); |
| 2916 | if b.Safi > safiMax { // frr5 and later work, ToDo: fix for older version |
| 2917 | return fmt.Errorf("unknown safi type: %d in version: %d (%s)", b.Type, version, software.string()) |
| 2918 | } |
| 2919 | data = data[1:] |
| 2920 | |
| 2921 | // zapi version 5 only |
| 2922 | if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, software) > 0 { |