forked from osrg/gobgp
/
zapi.go
3329 lines (3087 loc) · 103 KB
/
zapi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (C) 2014, 2015 Nippon Telegraph and Telephone Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package zebra
import (
"encoding/binary"
"errors"
"fmt"
"github.com/osrg/gobgp/pkg/packet/bgp"
log "github.com/sirupsen/logrus"
"io"
"math"
"net"
"strings"
"syscall"
)
const (
// MinZapiVer is minimum zebra api version which is referred in zclient
MinZapiVer uint8 = 2
// MaxZapiVer is maximum zebra api version which is referredd in zclient
MaxZapiVer uint8 = 6
// DefaultVrf is default vrf id is referredd in zclient and server
DefaultVrf = 0
)
const (
headerMarker uint8 = 255
frrHeaderMarker uint8 = 254
interfaceNameSize = 20
maxPathNum = 64
maxMplsLabel = 16
)
// Internal Interface Status.
type interfaceStatus uint8
const (
interfaceActive interfaceStatus = 0x01
interfaceSub interfaceStatus = 0x02
interfaceLinkDetection interfaceStatus = 0x04
interfaceVrfLoopback interfaceStatus = 0x08
)
// Interface Link Layer Types.
//go:generate stringer -type=linkType
type linkType uint32
const (
linkTypeUnknown linkType = iota
linkTypeEther
linkTypeEEther
linkTypeAX25
linkTypePRONET
linkTypeIeee802
linkTypeARCNET
linkTypeAPPLETLK
linkTypeDLCI
linkTypeATM
linkTypeMetricOM
linkTypeIeee1394
linkTypeEUI64
linkTypeINFINIBAND
linkTypeSLIP
linkTypeCSLIP
linkTypeSLIP6
linkTypeCSLIP6
linkTypeRSRVD
linkTypeADAPT
linkTypeROSE
linkTypeX25
linkTypePPP
linkTypeCHDLC
linkTypeLAPB
linkTypeRAWHDLC
linkTypeIPIP
linkTypeIPIP6
linkTypeFRAD
linkTypeSKIP
linkTypeLOOPBACK
linkTypeLOCALTLK
linkTypeFDDI
linkTypeSIT
linkTypeIPDDP
linkTypeIPGRE
linkTypeIP6GRE
linkTypePIMREG
linkTypeHIPPI
linkTypeECONET
linkTypeIRDA
linkTypeFCPP
linkTypeFCAL
linkTypeFCPL
linkTypeFCFABRIC
linkTypeIeee802Tr
linkTypeIeee80211
linkTypeIeee80211RadioTap
linkTypeIeee802154
linkTypeIeee802154Phy
)
const softwareNameMinimumVersion uint8 = 5
var allowableSoftwareNameArrays = [][]string{
{"frr4", "cumulus"}, //version:5
{"frr7.3", "frr7.2", "frr7", "frr6"}, //version:6
}
// IsAllowableSoftwareName returns bool from version number and softwareName
func IsAllowableSoftwareName(version uint8, softwareName string) bool {
if softwareName == "" {
return true
} else if version < softwareNameMinimumVersion { //version is less than 5
return false
}
for i, allowableSoftwareNames := range allowableSoftwareNameArrays {
if version != uint8(i)+softwareNameMinimumVersion {
continue
}
for _, allowableSoftwareName := range allowableSoftwareNames {
if softwareName == allowableSoftwareName {
return true
}
}
}
return false
}
// HeaderSize returns suitable header size from version
func HeaderSize(version uint8) uint16 {
switch version {
case 3, 4:
return 8
case 5, 6:
return 10
}
return 6 // version == 2
}
// HeaderMarker returns suitable header marker from version
func HeaderMarker(version uint8) uint8 {
if version > 3 {
return frrHeaderMarker
}
return headerMarker
}
func (t interfaceStatus) String() string {
ss := make([]string, 0, 3)
if t&interfaceActive > 0 {
ss = append(ss, "Active")
}
if t&interfaceSub > 0 {
ss = append(ss, "Sub")
}
if t&interfaceLinkDetection > 0 {
ss = append(ss, "LinkDetection")
}
if t&interfaceVrfLoopback > 0 {
ss = append(ss, "VrfLoopback")
}
return strings.Join(ss, "|")
}
// Interface Connected Address Flags
type interfaceAddressFlag uint8
const (
interfaceAddressSecondary interfaceAddressFlag = 0x01
interfaceAddressPeer interfaceAddressFlag = 0x02
interfaceAddressUnnumbered interfaceAddressFlag = 0x04
)
func (t interfaceAddressFlag) String() string {
ss := make([]string, 0, 3)
if t&interfaceAddressSecondary > 0 {
ss = append(ss, "SECONDARY")
}
if t&interfaceAddressPeer > 0 {
ss = append(ss, "PEER")
}
if t&interfaceAddressUnnumbered > 0 {
ss = append(ss, "UNNUMBERED")
}
return strings.Join(ss, "|")
}
// Address Family IDentifier.
//go:generate stringer -type=afi
type afi uint8
const (
afiIP afi = 1
afiIP6 afi = 2
afiEther afi = 3
afiMax afi = 4
)
// Safi is Subsequent Address Family IDentifier.
//go:generate stringer -type=Safi
type Safi uint8
// Safi definition in Zebra of FRRouting 4.x, 5.x, 6.x, and 7.x
const (
safiUnspec Safi = iota // add in FRRouting version 7.2 (Zapi 6)
SafiUnicast
safiMulticast
safiMplsVpn
safiEncap
safiEvpn
safiLabeledUnicast
safiFlowspec // add in FRRouting version 5 (Zapi 5)
safiMax
)
// Safi definition in Zebra of Quagga and FRRouting 3.x
const (
zapi4SafiMplsVpn Safi = iota + safiMulticast + 1 // SafiRESERVED_3 in quagga
zapi3SafiMplsVpn // SafiRESERVED_4 in FRRouting 3.x
zapi4SafiEncap
zapi4SafiEvpn
zapi3SafiEncap // SafiMax in FRRouting 3.x
)
var zapi3SafiMap = map[Safi]Safi{
zapi3SafiMplsVpn: safiMplsVpn,
zapi3SafiEncap: safiEncap,
}
var zapi4SafiMap = map[Safi]Safi{
zapi4SafiMplsVpn: safiMplsVpn,
zapi4SafiEncap: safiEncap,
zapi4SafiEvpn: safiEvpn,
}
var safiRouteFamilyIPv4Map = map[Safi]bgp.RouteFamily{
safiUnspec: bgp.RF_OPAQUE,
SafiUnicast: bgp.RF_IPv4_UC,
safiMulticast: bgp.RF_IPv4_MC,
safiMplsVpn: bgp.RF_IPv4_VPN,
safiEncap: bgp.RF_IPv4_ENCAP,
safiLabeledUnicast: bgp.RF_IPv4_MPLS,
safiFlowspec: bgp.RF_FS_IPv4_UC,
}
var safiRouteFamilyIPv6Map = map[Safi]bgp.RouteFamily{
safiUnspec: bgp.RF_OPAQUE,
SafiUnicast: bgp.RF_IPv6_UC,
safiMulticast: bgp.RF_IPv6_MC,
safiMplsVpn: bgp.RF_IPv6_VPN,
safiEncap: bgp.RF_IPv6_ENCAP,
safiLabeledUnicast: bgp.RF_IPv6_MPLS,
safiFlowspec: bgp.RF_FS_IPv6_UC,
}
// APIType is referred in zclient_test.
//go:generate stringer -type=APIType
type APIType uint16
// For FRRouting version 7.3 (ZAPI version 6)
const (
interfaceAdd APIType = iota // 0 // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3
interfaceDelete // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3
interfaceAddressAdd // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3
interfaceAddressDelete // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3
interfaceUp // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3
interfaceDown // same ID in frr3, 4, 5, 6, 7.0, 7.1. 7.2. 7.3
_interfaceSetMaster
_interfaceSetProtoDown // Add in frr 7.2
RouteAdd // RouteAdd is referred in zclient_test
RouteDelete // RouteDelete is referred in zclient_test
_routeNotifyOwner // 10
redistributeAdd
_redistributeDelete
_redistributeDefaultAdd
_redistributeDefaultDelete
routerIDAdd
_routerIDDelete
routerIDUpdate
hello
_capabilities // add in frr5
nexthopRegister // 20
nexthopUnregister
nexthopUpdate
_interfaceNBRAddressAdd
_interfaceNBRAddressDelete
_interfaceBFDDestUpdate
_importRouteRegister
_importRouteUnregister
_importCheckUpdate
_bfdDestRegister
_bfdDestDeregister // 30
_bfdDestUpdate
_bfdDestReplay
redistributeRouteAdd
redistributeRouteDel
_vrfUnregister
_vrfAdd
_vrfDelete
vrfLabel // add in frr5
_interfaceVRFUpdate
_bfdClientRegister // 40
_bfdClientDeregister
_interfaceEnableRADV
_interfaceDisableRADV
ipv4NexthopLookupMRIB
_interfaceLinkParams
_mplsLabelsAdd
_mplsLabelsDelete
_mplsLabelsReplace // add in frr7.3
_srPolicySet // add in frr7.5
_srPolicyDelete // 50 // add in frr7.5
_srPolicyNotifyStatus // add in frr7.5
_ipmrRouteStats
labelManagerConnect // 53
labelManagerConnectAsync // add in frr5
getLabelChunk
releaseLabelChunk
_fecRegister
_fecUnregister
_fecUpdate
_advertiseDefaultGW // 60
_advertiseSviMACIP // add in frr7.1
_advertiseSubnet
_advertiseAllVNI // 63
_localESAdd
_localESDel // 65
_remoteESVTEPAdd // add in frr7.5
_remoteESVTEPDel // add in frr7.5
_localESEVIAdd // add in frr7.5
_localESEVIDel // add in frr7.5
_vniAdd // 70
_vniDel
_l3VNIAdd
_l3VNIDel
_remoteVTEPAdd
_remoteVTEPDel
_macIPAdd
_macIPDel // 77
_ipPrefixRouteAdd
_ipPrefixRouteDel
_remoteMACIPAdd // 80
_remoteMACIPDel
_duplicateAddrDetection
_pwAdd
_pwDelete
_pwSet
_pwUnset
_pwStatusUpdate // 87
_ruleAdd
_ruleDelete
_ruleNotifyOwner // 90
_tableManagerConnect
_getTableChunk
_releaseTableChunk
_ipSetCreate
_ipSetDestroy
_ipSetEntryAdd
_ipSetEntryDelete // 97
_ipSetNotifyOwner
_ipSetEntryNotifyOwner
_ipTableAdd // 100
_ipTableDelete
_ipTableNotifyOwner
_vxlanFloodControl
_vxlanSgAdd
_vxlanSgDel
_vxlanSgReplay
_mlagProcessUp // 107 // add in frr7.3
_mlagProcessDown // add in frr7.3
_mlagClientRegister // add in frr7.3
_mlagClientUnregister // 110 // add in frr7.3
_mlagClientForwardMsg // add in frr7.3
zebraError // add in frr7.3
_clientCapabilities // add in frr7.4
_opaqueMessage // add in frr7.5
_opaqueRegister // add in frr7.5
_opaqueUnregister // add in frr7.5
_neighDiscover // 117 // add in frr7.5
// BackwardIPv6RouteAdd is referred in zclient_test
BackwardIPv6RouteAdd // quagga, frr3, frr4, frr5
// BackwardIPv6RouteDelete is referred in zclient_test
BackwardIPv6RouteDelete // quagga, frr3, frr4, frr5
)
const (
zapi6Frr7dot3MinDifferentAPIType APIType = 49 //frr7.3(zapi6)
zapi6Frr7dot2MinDifferentAPIType APIType = 48 //frr7.2(zapi6)
zapi5ClMinDifferentAPIType APIType = 19 //cumuluslinux3.7.7, zebra4.0+cl3u13(zapi5)
zapi5MinDifferentAPIType APIType = 7 //frr4&5(zapi5), frr6&7.0&7.1(zapi6)
zapi4MinDifferentAPIType APIType = 6
zapi3MinDifferentAPIType APIType = 0
)
func minDifferentAPIType(version uint8, softwareName string) APIType {
if version < 4 {
return zapi3MinDifferentAPIType
} else if version == 4 {
return zapi4MinDifferentAPIType
} else if version == 5 && softwareName == "cumulus" {
return zapi5ClMinDifferentAPIType
} else if version == 5 ||
(version == 6 && (softwareName == "frr6" || softwareName == "frr7")) {
return zapi5MinDifferentAPIType
} else if version == 6 && softwareName == "frr7.2" {
return zapi6Frr7dot2MinDifferentAPIType
}
return zapi6Frr7dot3MinDifferentAPIType
}
const (
zapi6Frr7dot3LabelManagerConnect APIType = 50 // difference from frr7.5
zapi6Frr7dot3LabelManagerConnectAsync APIType = 51 // difference from frr7.5
zapi6Frr7dot3GetLabelChunk APIType = 52 // difference from frr7.5
zapi6Frr7dot3ReleaseLabelChunk APIType = 53 // difference from frr7.5
)
var apiTypeZapi6Frr7dot3Map = map[APIType]APIType{
labelManagerConnect: zapi6Frr7dot3LabelManagerConnect,
labelManagerConnectAsync: zapi6Frr7dot3LabelManagerConnectAsync,
getLabelChunk: zapi6Frr7dot3GetLabelChunk,
releaseLabelChunk: zapi6Frr7dot3ReleaseLabelChunk,
}
const (
zapi6Frr7dot2LabelManagerConnect APIType = 49 // difference from frr7.5
zapi6Frr7dot2LabelManagerConnectAsync APIType = 50 // difference from frr7.5
zapi6Frr7dot2GetLabelChunk APIType = 51 // difference from frr7.5
zapi6Frr7dot2ReleaseLabelChunk APIType = 52 // difference from frr7.5
)
var apiTypeZapi6Frr7dot2Map = map[APIType]APIType{
labelManagerConnect: zapi6Frr7dot2LabelManagerConnect,
labelManagerConnectAsync: zapi6Frr7dot2LabelManagerConnectAsync,
getLabelChunk: zapi6Frr7dot2GetLabelChunk,
releaseLabelChunk: zapi6Frr7dot2ReleaseLabelChunk,
}
const ( // frr7.0, 7.1
zapi6Frr7RouteAdd APIType = 7
zapi6Frr7RouteDelete APIType = 8
zapi6Frr7RedistributAdd APIType = 10
zapi6Frr7RouterIDAdd APIType = 14
zapi6Frr7RouterIDUpdate APIType = 16
zapi6Frr7Hello APIType = 17
zapi6Frr7NexthopRegister APIType = 19
zapi6Frr7NexthopUnregister APIType = 20
zapi6Frr7NexthopUpdate APIType = 21
zapi6Frr7RedistributeRouteAdd APIType = 32
zapi6Frr7RedistributeRouteDel APIType = 33
zapi6Frr7VrfLabel APIType = 37
zapi6Frr7Ipv4NexthopLookupMRIB APIType = 43
zapi6Frr7LabelManagerConnect APIType = 48
zapi6Frr7LabelManagerConnectAsync APIType = 49
zapi6Frr7GetLabelChunk APIType = 50
zapi6Frr7ReleaseLabelChunk APIType = 51
)
var apiTypeZapi6Frr7Map = map[APIType]APIType{ // frr7.0, 7.1
RouteAdd: zapi6Frr7RouteAdd,
RouteDelete: zapi6Frr7RouteDelete,
redistributeAdd: zapi6Frr7RedistributAdd,
routerIDAdd: zapi6Frr7RouterIDAdd,
routerIDUpdate: zapi6Frr7RouterIDUpdate,
hello: zapi6Frr7Hello,
nexthopRegister: zapi6Frr7NexthopRegister,
nexthopUnregister: zapi6Frr7NexthopUnregister,
nexthopUpdate: zapi6Frr7NexthopUpdate,
redistributeRouteAdd: zapi6Frr7RedistributeRouteAdd,
redistributeRouteDel: zapi6Frr7RedistributeRouteDel,
vrfLabel: zapi6Frr7VrfLabel,
ipv4NexthopLookupMRIB: zapi6Frr7Ipv4NexthopLookupMRIB,
labelManagerConnect: zapi6Frr7LabelManagerConnect,
labelManagerConnectAsync: zapi6Frr7LabelManagerConnectAsync,
getLabelChunk: zapi6Frr7GetLabelChunk,
releaseLabelChunk: zapi6Frr7ReleaseLabelChunk,
}
var apiTypeZapi6Frr6Map = map[APIType]APIType{
RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1
RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1
redistributeAdd: zapi6Frr7RedistributAdd, // same as frr7.0&7.1
routerIDAdd: zapi6Frr7RouterIDAdd, // same as frr7.0&7.1
routerIDUpdate: zapi6Frr7RouterIDUpdate, // same as frr7.0&7.1
hello: zapi6Frr7Hello, // same as frr7.0&7.1
nexthopRegister: zapi6Frr7NexthopRegister, // same as frr7.0&7.1
nexthopUnregister: zapi6Frr7NexthopUnregister, // same as frr7.0&7.1
nexthopUpdate: zapi6Frr7NexthopUpdate, // same as frr7.0&7.1
redistributeRouteAdd: redistributeRouteAdd, // same as frr7.2&7.3
redistributeRouteDel: redistributeRouteDel, // same as frr7.2&7.3
vrfLabel: vrfLabel, // same as frr7.2&7.3
ipv4NexthopLookupMRIB: ipv4NexthopLookupMRIB, // same as frr7.2&7.3
labelManagerConnect: zapi6Frr7dot2LabelManagerConnect, // same as frr7.2
labelManagerConnectAsync: zapi6Frr7dot2LabelManagerConnectAsync, // same as frr7.2
getLabelChunk: zapi6Frr7dot2GetLabelChunk, // same as frr7.2
releaseLabelChunk: zapi6Frr7dot2ReleaseLabelChunk, // same as frr7.2
}
const ( // For Cumulus Linux 3.7.7, zebra 4.0+cl3u13 (ZAPI version 5)
zapi5ClIpv4NexthopLookupMRIB APIType = 42
zapi5ClLabelManagerConnect APIType = 47
zapi5ClGetLabelChunk APIType = 48
zapi5ClReleaseLabelChunk APIType = 49
)
var apiTypeZapi5ClMap = map[APIType]APIType{
nexthopRegister: zapi6Frr7NexthopRegister, // same as frr7.0&7.1
nexthopUnregister: zapi6Frr7NexthopUnregister, // same as frr7.0&7.1
nexthopUpdate: zapi6Frr7NexthopUpdate, // same as frr7.0&7.1
redistributeRouteAdd: zapi6Frr7RedistributeRouteAdd, // same as frr7.0&7.1
redistributeRouteDel: zapi6Frr7RedistributeRouteDel, // same as frr7.0&7.1
vrfLabel: zapi6Frr7VrfLabel, // same as frr7.0&7.1
labelManagerConnect: zapi5ClLabelManagerConnect,
getLabelChunk: zapi5ClGetLabelChunk,
releaseLabelChunk: zapi5ClReleaseLabelChunk,
}
const (
zapi5RedistributAdd APIType = 14
zapi5RouterIDAdd APIType = 18
zapi5RouterIDUpdate APIType = 20
zapi5Hello APIType = 21
zapi5Frr5NexthopRegister APIType = 23
zapi5Frr5NexthopUnregister APIType = 24
zapi5Frr5NexthopUpdate APIType = 25
zapi5Frr5RedistributeRouteAdd APIType = 37
zapi5Frr5RedistributeRouteDel APIType = 38
zapi5Frr5VrfLabel APIType = 42
zapi5Frr5Ipv4NexthopLookupMRIB APIType = 47
zapi5Frr5LabelManagerConnect APIType = 52
zapi5Frr5LabelManagerConnectAsync APIType = 53
zapi5Frr5GetLabelChunk APIType = 54
zapi5Frr5ReleaseLabelChunk APIType = 55
)
var apiTypeZapi5Frr5Map = map[APIType]APIType{
RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1
RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1
redistributeAdd: zapi5RedistributAdd,
routerIDAdd: zapi5RouterIDAdd,
routerIDUpdate: zapi5RouterIDUpdate,
hello: zapi5Hello,
nexthopRegister: zapi5Frr5NexthopRegister,
nexthopUnregister: zapi5Frr5NexthopUnregister,
nexthopUpdate: zapi5Frr5NexthopUpdate,
redistributeRouteAdd: zapi5Frr5RedistributeRouteAdd,
redistributeRouteDel: zapi5Frr5RedistributeRouteDel,
vrfLabel: zapi5Frr5VrfLabel,
ipv4NexthopLookupMRIB: zapi5Frr5Ipv4NexthopLookupMRIB,
labelManagerConnect: zapi5Frr5LabelManagerConnect,
labelManagerConnectAsync: zapi5Frr5LabelManagerConnectAsync,
getLabelChunk: zapi5Frr5GetLabelChunk,
releaseLabelChunk: zapi5Frr5ReleaseLabelChunk,
}
const (
zapi5Frr4NexthopRegister APIType = 22
zapi5Frr4NexthopUnregister APIType = 23
zapi5Frr4NexthopUpdate APIType = 24
zapi5Frr4RedistributeRouteAdd APIType = 36
zapi5Frr4RedistributeRouteDel APIType = 37
zapi5Frr4Ipv4NexthopLookupMRIB APIType = 45
zapi5Frr4LabelManagerConnect APIType = 50
zapi5Frr4GetLabelChunk APIType = 51
zapi5Frr4ReleaseLabelChunk APIType = 52
)
var apiTypeZapi5Frr4Map = map[APIType]APIType{
RouteAdd: zapi6Frr7RouteAdd, // same as frr7.0&7.1
RouteDelete: zapi6Frr7RouteDelete, // same as frr7.0&7.1
redistributeAdd: zapi5RedistributAdd,
routerIDAdd: zapi5RouterIDAdd,
routerIDUpdate: zapi5RouterIDUpdate,
hello: zapi5Hello,
nexthopRegister: zapi5Frr4NexthopRegister,
nexthopUnregister: zapi5Frr4NexthopUnregister,
nexthopUpdate: zapi5Frr4NexthopUpdate,
redistributeRouteAdd: zapi5Frr4RedistributeRouteAdd,
redistributeRouteDel: zapi5Frr4RedistributeRouteDel,
ipv4NexthopLookupMRIB: zapi5Frr4Ipv4NexthopLookupMRIB,
labelManagerConnect: zapi5Frr4LabelManagerConnect,
getLabelChunk: zapi5Frr4GetLabelChunk,
releaseLabelChunk: zapi5Frr4ReleaseLabelChunk,
}
const (
zapi4IPv4RouteAdd APIType = 6 // deleted in zapi6
zapi4IPv4RouteDelete APIType = 7 // deleted in zapi6
zapi4IPv6RouteAdd APIType = 8 // deleted in zapi6
zapi4IPv6RouteDelete APIType = 9 // deleted in zapi6
zapi4RedistributAdd APIType = 10
zapi4RouterIDAdd APIType = 14
zapi4RouterIDUpdate APIType = 16
zapi4Hello APIType = 17
zapi4NexthopRegister APIType = 18
zapi4NexthopUnregister APIType = 19
zapi4NexthopUpdate APIType = 20
zapi4RedistributeIPv4Add APIType = 32 // deleted in zapi6
zapi4RedistributeIPv4Del APIType = 33 // deleted in zapi6
zapi4RedistributeIPv6Add APIType = 34 // deleted in zapi6
zapi4RedistributeIPv6Del APIType = 35 // deleted in zapi6
zapi4LabelManagerConnect APIType = 52
zapi4GetLabelChunk APIType = 53
zapi4ReleaseLabelChunk APIType = 54
)
var apiTypeZapi4Map = map[APIType]APIType{
RouteAdd: zapi4IPv4RouteAdd, // deleted in zapi5
RouteDelete: zapi4IPv4RouteDelete, // deleted in zapi5
redistributeAdd: zapi4RedistributAdd,
routerIDAdd: zapi4RouterIDAdd,
routerIDUpdate: zapi4RouterIDUpdate,
hello: zapi4Hello,
nexthopRegister: zapi4NexthopRegister,
nexthopUnregister: zapi4NexthopUnregister,
nexthopUpdate: zapi4NexthopUpdate,
redistributeRouteAdd: zapi4RedistributeIPv4Add, // deleted in zapi5
redistributeRouteDel: zapi4RedistributeIPv4Del, // deleted in zapi5
ipv4NexthopLookupMRIB: zapi6Frr7Ipv4NexthopLookupMRIB, // same as frr7.0&7.1
labelManagerConnect: zapi4LabelManagerConnect,
getLabelChunk: zapi4GetLabelChunk,
releaseLabelChunk: zapi4ReleaseLabelChunk,
BackwardIPv6RouteAdd: zapi4IPv6RouteAdd,
BackwardIPv6RouteDelete: zapi4IPv6RouteDelete,
}
const (
zapi3InterfaceAdd APIType = 1
zapi3InterfaceDelete APIType = 2
zapi3InterfaceAddressAdd APIType = 3
zapi3InterfaceAddressDelete APIType = 4
zapi3InterfaceUp APIType = 5
zapi3InterfaceDown APIType = 6
zapi3IPv4RouteAdd APIType = 7 // deleted in zapi5
zapi3IPv4RouteDelete APIType = 8 // deleted in zapi5
zapi3IPv6RouteAdd APIType = 9 // deleted in zapi5
zapi3IPv6RouteDelete APIType = 10 // deleted in zapi5
zapi3RedistributeAdd APIType = 11
zapi3IPv4NexthopLookup APIType = 15 // zapi3(quagga) only
zapi3IPv6NexthopLookup APIType = 16 // zapi3(quagga) only
zapi3IPv4ImportLookup APIType = 17 // zapi3(quagga) only
zapi3RouterIDAdd APIType = 20
zapi3RouterIDUpdate APIType = 22
zapi3Hello APIType = 23
zapi3Ipv4NexthopLookupMRIB APIType = 24
zapi3NexthopRegister APIType = 27
zapi3NexthopUnregister APIType = 28
zapi3NexthopUpdate APIType = 29
)
var apiTypeZapi3Map = map[APIType]APIType{
interfaceAdd: zapi3InterfaceAdd,
interfaceDelete: zapi3InterfaceDelete,
interfaceAddressAdd: zapi3InterfaceAddressAdd,
interfaceAddressDelete: zapi3InterfaceAddressDelete,
interfaceUp: zapi3InterfaceUp,
interfaceDown: zapi3InterfaceDown,
RouteAdd: zapi3IPv4RouteAdd, // deleted in zapi5
RouteDelete: zapi3IPv4RouteDelete, // deleted in zapi5
redistributeAdd: zapi3RedistributeAdd,
routerIDAdd: zapi3RouterIDAdd,
routerIDUpdate: zapi3RouterIDUpdate,
hello: zapi3Hello,
nexthopRegister: zapi3NexthopRegister,
nexthopUnregister: zapi3NexthopUnregister,
nexthopUpdate: zapi3NexthopUpdate,
BackwardIPv6RouteAdd: zapi3IPv6RouteAdd,
BackwardIPv6RouteDelete: zapi3IPv6RouteDelete,
}
func (t APIType) doesNeedConversion(version uint8, softwareName string) bool {
if (version == 6 && softwareName == "") || t < minDifferentAPIType(version, softwareName) {
return false
}
return true
}
func apiTypeMap(version uint8, softwareName string) map[APIType]APIType {
if version == 6 && softwareName == "frr7.2" {
return apiTypeZapi6Frr7dot2Map
} else if version == 6 && softwareName == "frr7" {
return apiTypeZapi6Frr7Map
} else if version == 6 && softwareName == "frr6" {
return apiTypeZapi6Frr6Map
} else if version == 5 {
if softwareName == "frr4" {
return apiTypeZapi5Frr4Map
} else if softwareName == "cumulus" {
return apiTypeZapi5ClMap
}
return apiTypeZapi5Frr5Map
} else if version == 4 {
return apiTypeZapi4Map
} else if version < 4 {
return apiTypeZapi3Map
}
return apiTypeZapi6Frr7dot3Map
}
// ToEach is referred in zclient_test
func (t APIType) ToEach(version uint8, softwareName string) APIType {
if !t.doesNeedConversion(version, softwareName) {
return t
}
apiMap := apiTypeMap(version, softwareName)
backward, ok := apiMap[t]
if !ok {
backward = zebraError // fail to convert and error value
}
log.WithFields(log.Fields{
"Topic": "Zebra",
}).Debugf("zebra ToEach converts APIType: %d(%s) -> %d (version: %d, software: %s)",
t, t.String(), backward, version, softwareName)
return backward // success to convert
}
func (t APIType) toCommon(version uint8, softwareName string) APIType {
if !t.doesNeedConversion(version, softwareName) {
return t
}
apiMap := apiTypeMap(version, softwareName)
for common, backward := range apiMap {
if backward == t {
log.WithFields(log.Fields{
"Topic": "Zebra",
}).Debugf("zebra toCommon converts APIType: %d -> %d(%s) (version: %d, software: %s)",
t, common, common.String(), version, softwareName)
return common // success to convert
}
}
return zebraError // fail to convert and error value
}
func (t APIType) addressFamily(version uint8) uint8 {
if version == 4 {
switch t {
case zapi4IPv4RouteAdd, zapi4IPv4RouteDelete, zapi4RedistributeIPv4Add, zapi4RedistributeIPv4Del, zapi6Frr7Ipv4NexthopLookupMRIB:
return syscall.AF_INET
case zapi4IPv6RouteAdd, zapi4IPv6RouteDelete, zapi4RedistributeIPv6Add, zapi4RedistributeIPv6Del:
return syscall.AF_INET6
}
} else if version < 4 {
switch t {
case zapi3IPv4RouteAdd, zapi3IPv4RouteDelete, zapi3IPv4NexthopLookup, zapi3IPv4ImportLookup, zapi3Ipv4NexthopLookupMRIB:
return syscall.AF_INET
case zapi3IPv6RouteAdd, zapi3IPv6RouteDelete, zapi3IPv6NexthopLookup:
return syscall.AF_INET6
}
}
return syscall.AF_UNSPEC
}
// RouteType is referred in zclient.
//go:generate stringer -type=RouteType
type RouteType uint8
// For FRRouting version 7 (ZAPI version 6).
const (
routeSystem RouteType = iota //0
routeKernel
routeConnect
RouteStatic
routeRIP
routeRIPNG
routeOSPF
routeOSPF6
routeISIS
RouteBGP
routePIM // 10
routeEIGRP // FRRRouting version 4 (Zapi5) adds.
routeNHRP
routeHSLS
routeOLSR
routeTABLE
routeLDP
routeVNC
routeVNCDirect
routeVNCDirectRH
routeBGPDirect
routeBGPDirectEXT
routeBABEL
routeSHARP
routePBR // FRRRouting version 5 (Zapi5) adds.
routeBFD // FRRRouting version 6 (Zapi6) adds.
routeOpenfabric // FRRRouting version 7 (Zapi6) adds.
routeVRRP // FRRRouting version 7.2 (Zapi6) adds.
routeNHG // FRRRouting version 7.3 (Zapi6) adds.
routeSRTE // FRRRouting version 7.5 (Zapi6) adds.
routeAll
routeMax // max value for error
)
const (
zapi5Frr4RouteAll RouteType = 24
zapi5Frr5RouteAll RouteType = 25
zapi6Frr6RouteAll RouteType = 26
zapi6Frr7RouteAll RouteType = 27
zapi6Frr7dot2RouteAll RouteType = 28
zapi6Frr7dot3RouteAll RouteType = 29
)
func getRouteAll(version uint8, softwareName string) RouteType {
if version == 5 {
if softwareName == "frr4" {
return zapi5Frr4RouteAll
}
return zapi5Frr5RouteAll
} else if version == 6 {
if softwareName == "frr6" {
return zapi6Frr6RouteAll
} else if softwareName == "frr7" {
return zapi6Frr7RouteAll
} else if softwareName == "frr7.2" {
return zapi6Frr7dot2RouteAll
} else if softwareName == "frr7.3" {
return zapi6Frr7dot3RouteAll
}
}
return routeAll
}
// For FRRouting version 3.0 except common route type.
const (
zapi4RouteNHRP RouteType = iota + routePIM + 1
zapi4RouteHSLS
zapi4RouteOLSR
zapi4RouteTABLE
zapi4RouteLDP
zapi4RouteVNC
zapi4RouteVNCDirect
zapi4RouteVNCDirectRH
zapi4RouteBGPDixrect
zapi4RouteBGPDirectEXT
zapi4RouteAll
)
var routeTypeZapi4Map = map[RouteType]RouteType{
routeNHRP: zapi4RouteNHRP,
routeHSLS: zapi4RouteHSLS,
routeOLSR: zapi4RouteOLSR,
routeTABLE: zapi4RouteTABLE,
routeLDP: zapi4RouteLDP,
routeVNC: zapi4RouteVNC,
routeVNCDirect: zapi4RouteVNCDirect,
routeVNCDirectRH: zapi4RouteVNCDirectRH,
routeBGPDirect: zapi4RouteBGPDixrect,
routeBGPDirectEXT: zapi4RouteBGPDirectEXT,
routeAll: zapi4RouteAll,
}
// For Quagga except common route type.
const (
zapi3RouteHSLS RouteType = iota + routePIM + 1
zapi3RouteOLSR
zapi3RouteBABEL
zapi3RouteNHRP // quagga 1.2.4
)
var routeTypeZapi3Map = map[RouteType]RouteType{
routeHSLS: zapi3RouteHSLS,
routeOLSR: zapi3RouteOLSR,
routeBABEL: zapi3RouteBABEL,
routeNHRP: zapi3RouteNHRP,
}
func (t RouteType) toEach(version uint8, softwareName string) RouteType {
if t <= routePIM || version > 4 { // not need to convert
return t
}
routeTypeMap := routeTypeZapi4Map
if version < 4 {
routeTypeMap = routeTypeZapi3Map
}
backward, ok := routeTypeMap[t]
if ok {
return backward // success to convert
}
return routeMax // fail to convert and error value
}
var routeTypeValueMap = map[string]RouteType{
"system": routeSystem,
"kernel": routeKernel,
"connect": routeConnect, // hack for backward compatibility
"directly-connected": routeConnect,
"static": RouteStatic,
"rip": routeRIP,
"ripng": routeRIPNG,
"ospf": routeOSPF,
"ospf3": routeOSPF6,
"isis": routeISIS,
"bgp": RouteBGP,
"pim": routePIM,
"eigrp": routeEIGRP, // add in frr4(zapi5)
"nhrp": routeNHRP,
"hsls": routeHSLS,
"olsr": routeOLSR,
"table": routeTABLE,
"ldp": routeLDP,
"vnc": routeVNC,
"vnc-direct": routeVNCDirect,
"vnc-rn": routeVNCDirectRH,
"bgp-direct": routeBGPDirect,
"bgp-direct-to-nve-groups": routeBGPDirectEXT,
"babel": routeBABEL,
"sharp": routeSHARP,
"pbr": routePBR,
"bfd": routeBFD,
"openfabric": routeOpenfabric, // add in frr7.0(zapi6)
"vrrp": routeVRRP, // add in frr7.2(zapi6)
"nhg": routeNHG, // add in frr7.3(zapi6)
"srte": routeSRTE, // add in frr7.5(zapi6)
"wildcard": routeAll,
}
// RouteTypeFromString converts from string to route type
func RouteTypeFromString(typ string, version uint8, softwareName string) (RouteType, error) {
t, ok := routeTypeValueMap[typ]
if !ok { // failed to lookup RouteType from string
return t, fmt.Errorf("unknown route type: %s in version: %d (%s)", typ, version, softwareName)
}
t = t.toEach(version, softwareName) //when lookup failes return routeMax
if t > getRouteAll(version, softwareName) {
return t, fmt.Errorf("unknown route type: %d in version: %d (%s)", t, version, softwareName)
}
return t, nil // Success
}
func addressByteLength(family uint8) (int, error) {
switch family {
case syscall.AF_INET:
return net.IPv4len, nil
case syscall.AF_INET6:
return net.IPv6len, nil
}
return 0, fmt.Errorf("unknown address family: %d", family)
}
func ipFromFamily(family uint8, buf []byte) net.IP {
switch family {
case syscall.AF_INET:
return net.IP(buf).To4()
case syscall.AF_INET6:
return net.IP(buf).To16()
}
return nil
}
// MessageFlag is the type of API Message Flags.
type MessageFlag uint32 // MESSAGE_FLAG is 32bit after frr7.5, 8bit before frr7.4
const ( // For FRRouting version 4, 5 and 6 (ZAPI version 5 and 6).
// MessageNexthop is referred in zclient
MessageNexthop MessageFlag = 0x01
// MessageDistance is referred in zclient_test
MessageDistance MessageFlag = 0x02
// MessageMetric is referred in zclient
MessageMetric MessageFlag = 0x04
messageTag MessageFlag = 0x08
// MessageMTU is referred in zclient_test
MessageMTU MessageFlag = 0x10
messageSRCPFX MessageFlag = 0x20
// MessageLabel is referred in zclient
MessageLabel MessageFlag = 0x40 // deleted in frr7.3
messageBackupNexthops MessageFlag = 0x40 // added in frr7.4
messageTableID MessageFlag = 0x80 // introduced in frr5
messageSRTE MessageFlag = 0x100 // introduced in frr7.5
)
const ( // For FRRouting.
messageIFIndex MessageFlag = 0x02
zapi4MessageDistance MessageFlag = 0x04
zapi4MessageMetric MessageFlag = 0x08
zapi4MessageTag MessageFlag = 0x10
zapi4MessageMTU MessageFlag = 0x20
zapi4MessageSRCPFX MessageFlag = 0x40
)
const ( // For Quagga.
zapi3MessageMTU MessageFlag = 0x10
zapi3MessageTag MessageFlag = 0x20
)
// ToEach is referred in zclient
func (f MessageFlag) ToEach(version uint8) MessageFlag {
if version > 4 { //zapi version 5, 6
return f
}
if version < 4 { //zapi version 3, 2
switch f {
case MessageMTU:
return zapi3MessageMTU
case messageTag:
return zapi3MessageTag