Ref: zapi_ipv4_route in lib/zclient.c of Quagga1.2.x&FRR3.x(ZAPI3&4) Ref: zapi_route_encode in lib/zclient.c of FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6)
(version uint8, software Software)
| 2680 | // Ref: zapi_ipv4_route in lib/zclient.c of Quagga1.2.x&FRR3.x(ZAPI3&4) |
| 2681 | // Ref: zapi_route_encode in lib/zclient.c of FRR4&FRR5&FRR6&FRR7.x&FRR8 (ZAPI5&6) |
| 2682 | func (b *IPRouteBody) serialize(version uint8, software Software) ([]byte, error) { |
| 2683 | var buf []byte |
| 2684 | numNexthop := len(b.Nexthops) |
| 2685 | |
| 2686 | bufInitSize := 12 // type(1)+instance(2)+flags(4)+message(4)+safi(1), frr7.4&newer |
| 2687 | switch version { |
| 2688 | case 2, 3: |
| 2689 | bufInitSize = 5 |
| 2690 | case 4: |
| 2691 | bufInitSize = 10 |
| 2692 | case 5: |
| 2693 | bufInitSize = 9 // type(1)+instance(2)+flags(4)+message(1)+safi(1) |
| 2694 | case 6: |
| 2695 | if software.name == "frr" && software.version < 7.4 { // frr6, 7, 7.2, 7.3 |
| 2696 | bufInitSize = 9 // type(1)+instance(2)+flags(4)+message(1)+safi(1) |
| 2697 | } |
| 2698 | } |
| 2699 | buf = make([]byte, bufInitSize) |
| 2700 | |
| 2701 | buf[0] = uint8(b.Type.toEach(version)) // frr: stream_putc(s, api->type); |
| 2702 | if version < 4 { |
| 2703 | buf[1] = uint8(b.Flags) |
| 2704 | buf[2] = uint8(b.Message) |
| 2705 | binary.BigEndian.PutUint16(buf[3:5], uint16(b.Safi)) |
| 2706 | } else { // version >= 4 |
| 2707 | // frr: stream_putw(s, api->instance); |
| 2708 | binary.BigEndian.PutUint16(buf[1:3], b.instance) |
| 2709 | // frr: stream_putl(s, api->flags); |
| 2710 | binary.BigEndian.PutUint32(buf[3:7], uint32(b.Flags)) |
| 2711 | if version == 6 && software.name == "frr" && software.version >= 7.5 { |
| 2712 | // frr7.5 and newer: stream_putl(s, api->message); |
| 2713 | binary.BigEndian.PutUint32(buf[7:11], uint32(b.Message)) |
| 2714 | buf[11] = uint8(b.Safi) // stream_putc(s, api->safi); |
| 2715 | } else { |
| 2716 | // frr 7.4 and older: stream_putc(s, api->message); |
| 2717 | buf[7] = uint8(b.Message) |
| 2718 | if version > 4 { |
| 2719 | buf[8] = uint8(b.Safi) // frr: stream_putc(s, api->safi); |
| 2720 | } else { // version 2,3 and 4 (quagga, frr3) |
| 2721 | binary.BigEndian.PutUint16(buf[8:10], uint16(b.Safi)) |
| 2722 | } |
| 2723 | } |
| 2724 | } |
| 2725 | // only zapi version 5 (frr4.0.x) have evpn routes |
| 2726 | if version == 5 && b.Flags&flagEvpnRoute.ToEach(version, software) > 0 { |
| 2727 | // size of struct ethaddr is 6 octets defined by ETH_ALEN |
| 2728 | buf = append(buf, b.Nexthops[numNexthop-1].rmac[:6]...) |
| 2729 | } |
| 2730 | if version > 4 { // version 5, 6 (after frr4) |
| 2731 | if b.Prefix.Family == syscall.AF_UNSPEC { |
| 2732 | b.Prefix.Family = familyFromPrefix(b.Prefix.Prefix) |
| 2733 | } |
| 2734 | // frr: stream_putc(s, api->prefix.family); |
| 2735 | buf = append(buf, b.Prefix.Family) |
| 2736 | } |
| 2737 | byteLen := (int(b.Prefix.PrefixLen) + 7) / 8 |
| 2738 | buf = append(buf, b.Prefix.PrefixLen) // frr: stream_putc(s, api->prefix.prefixlen); |
| 2739 | // frr: stream_write(s, (uint8_t *)&api->prefix.u.prefix, psize); |