|
@@ -29,9 +29,10 @@ import (
|
29
|
29
|
)
|
30
|
30
|
|
31
|
31
|
const (
|
32
|
|
- AFI_IP = 1
|
33
|
|
- AFI_IP6 = 2
|
34
|
|
- AFI_L2VPN = 25
|
|
32
|
+ AFI_IP = 1
|
|
33
|
+ AFI_IP6 = 2
|
|
34
|
+ AFI_L2VPN = 25
|
|
35
|
+ AFI_OPAQUE = 16397
|
35
|
36
|
)
|
36
|
37
|
|
37
|
38
|
const (
|
|
@@ -46,6 +47,7 @@ const (
|
46
|
47
|
SAFI_ROUTE_TARGET_CONSTRTAINS = 132
|
47
|
48
|
SAFI_FLOW_SPEC_UNICAST = 133
|
48
|
49
|
SAFI_FLOW_SPEC_VPN = 134
|
|
50
|
+ SAFI_KEY_VALUE = 241
|
49
|
51
|
)
|
50
|
52
|
|
51
|
53
|
const (
|
|
@@ -86,9 +88,8 @@ const (
|
86
|
88
|
EC_TYPE_NON_TRANSITIVE_OPAQUE ExtendedCommunityAttrType = 0x43
|
87
|
89
|
EC_TYPE_NON_TRANSITIVE_QOS_MARKING ExtendedCommunityAttrType = 0x44
|
88
|
90
|
EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL ExtendedCommunityAttrType = 0x80
|
89
|
|
- //draft-ietf-idr-flowspec-redirect-rt-bis-05
|
90
|
|
- EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2 ExtendedCommunityAttrType = 0x81
|
91
|
|
- EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3 ExtendedCommunityAttrType = 0x82
|
|
91
|
+ EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL2 ExtendedCommunityAttrType = 0x81 // RFC7674
|
|
92
|
+ EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL3 ExtendedCommunityAttrType = 0x82 // RFC7674
|
92
|
93
|
)
|
93
|
94
|
|
94
|
95
|
// RFC7153 5.2. Registraction for the "Sub-Type" Field
|
|
@@ -1164,6 +1165,27 @@ func NewMPLSLabelStack(labels ...uint32) *MPLSLabelStack {
|
1164
|
1165
|
return &MPLSLabelStack{labels}
|
1165
|
1166
|
}
|
1166
|
1167
|
|
|
1168
|
+func ParseMPLSLabelStack(buf string) (*MPLSLabelStack, error) {
|
|
1169
|
+ elems := strings.Split(buf, "/")
|
|
1170
|
+ labels := make([]uint32, 0, len(elems))
|
|
1171
|
+ if len(elems) == 0 {
|
|
1172
|
+ goto ERR
|
|
1173
|
+ }
|
|
1174
|
+ for _, elem := range elems {
|
|
1175
|
+ i, err := strconv.Atoi(elem)
|
|
1176
|
+ if err != nil {
|
|
1177
|
+ goto ERR
|
|
1178
|
+ }
|
|
1179
|
+ if i < 0 || i > ((1<<20)-1) {
|
|
1180
|
+ goto ERR
|
|
1181
|
+ }
|
|
1182
|
+ labels = append(labels, uint32(i))
|
|
1183
|
+ }
|
|
1184
|
+ return NewMPLSLabelStack(labels...), nil
|
|
1185
|
+ERR:
|
|
1186
|
+ return nil, fmt.Errorf("invalid mpls label stack format")
|
|
1187
|
+}
|
|
1188
|
+
|
1167
|
1189
|
//
|
1168
|
1190
|
// RFC3107 Carrying Label Information in BGP-4
|
1169
|
1191
|
//
|
|
@@ -1338,6 +1360,10 @@ func (l *LabeledIPAddrPrefix) Serialize() ([]byte, error) {
|
1338
|
1360
|
return buf, nil
|
1339
|
1361
|
}
|
1340
|
1362
|
|
|
1363
|
+func (l *LabeledIPAddrPrefix) String() string {
|
|
1364
|
+ return fmt.Sprintf("%s/%d", l.Prefix.String(), int(l.Length)-l.Labels.Len()*8)
|
|
1365
|
+}
|
|
1366
|
+
|
1341
|
1367
|
func NewLabeledIPAddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPAddrPrefix {
|
1342
|
1368
|
return &LabeledIPAddrPrefix{
|
1343
|
1369
|
IPAddrPrefixDefault{length + uint8(label.Len()*8), net.ParseIP(prefix).To4()},
|
|
@@ -1350,6 +1376,10 @@ type LabeledIPv6AddrPrefix struct {
|
1350
|
1376
|
LabeledIPAddrPrefix
|
1351
|
1377
|
}
|
1352
|
1378
|
|
|
1379
|
+func (l *LabeledIPv6AddrPrefix) AFI() uint16 {
|
|
1380
|
+ return AFI_IP6
|
|
1381
|
+}
|
|
1382
|
+
|
1353
|
1383
|
func NewLabeledIPv6AddrPrefix(length uint8, prefix string, label MPLSLabelStack) *LabeledIPv6AddrPrefix {
|
1354
|
1384
|
return &LabeledIPv6AddrPrefix{
|
1355
|
1385
|
LabeledIPAddrPrefix{
|
|
@@ -2039,39 +2069,72 @@ const (
|
2039
|
2069
|
FLOW_SPEC_TYPE_DSCP
|
2040
|
2070
|
FLOW_SPEC_TYPE_FRAGMENT
|
2041
|
2071
|
FLOW_SPEC_TYPE_LABEL
|
|
2072
|
+ FLOW_SPEC_TYPE_ETHERNET_TYPE // 14
|
|
2073
|
+ FLOW_SPEC_TYPE_SRC_MAC
|
|
2074
|
+ FLOW_SPEC_TYPE_DST_MAC
|
|
2075
|
+ FLOW_SPEC_TYPE_LLC_DSAP
|
|
2076
|
+ FLOW_SPEC_TYPE_LLC_SSAP
|
|
2077
|
+ FLOW_SPEC_TYPE_LLC_CONTROL
|
|
2078
|
+ FLOW_SPEC_TYPE_SNAP
|
|
2079
|
+ FLOW_SPEC_TYPE_VID
|
|
2080
|
+ FLOW_SPEC_TYPE_COS
|
|
2081
|
+ FLOW_SPEC_TYPE_INNER_VID
|
|
2082
|
+ FLOW_SPEC_TYPE_INNER_COS
|
2042
|
2083
|
)
|
2043
|
2084
|
|
2044
|
2085
|
var FlowSpecNameMap = map[BGPFlowSpecType]string{
|
2045
|
|
- FLOW_SPEC_TYPE_UNKNOWN: "unknown",
|
2046
|
|
- FLOW_SPEC_TYPE_DST_PREFIX: "destination",
|
2047
|
|
- FLOW_SPEC_TYPE_SRC_PREFIX: "source",
|
2048
|
|
- FLOW_SPEC_TYPE_IP_PROTO: "protocol",
|
2049
|
|
- FLOW_SPEC_TYPE_PORT: "port",
|
2050
|
|
- FLOW_SPEC_TYPE_DST_PORT: "destination-port",
|
2051
|
|
- FLOW_SPEC_TYPE_SRC_PORT: "source-port",
|
2052
|
|
- FLOW_SPEC_TYPE_ICMP_TYPE: "icmp-type",
|
2053
|
|
- FLOW_SPEC_TYPE_ICMP_CODE: "icmp-code",
|
2054
|
|
- FLOW_SPEC_TYPE_TCP_FLAG: "tcp-flags",
|
2055
|
|
- FLOW_SPEC_TYPE_PKT_LEN: "packet-length",
|
2056
|
|
- FLOW_SPEC_TYPE_DSCP: "dscp",
|
2057
|
|
- FLOW_SPEC_TYPE_FRAGMENT: "fragment",
|
2058
|
|
- FLOW_SPEC_TYPE_LABEL: "label",
|
|
2086
|
+ FLOW_SPEC_TYPE_UNKNOWN: "unknown",
|
|
2087
|
+ FLOW_SPEC_TYPE_DST_PREFIX: "destination",
|
|
2088
|
+ FLOW_SPEC_TYPE_SRC_PREFIX: "source",
|
|
2089
|
+ FLOW_SPEC_TYPE_IP_PROTO: "protocol",
|
|
2090
|
+ FLOW_SPEC_TYPE_PORT: "port",
|
|
2091
|
+ FLOW_SPEC_TYPE_DST_PORT: "destination-port",
|
|
2092
|
+ FLOW_SPEC_TYPE_SRC_PORT: "source-port",
|
|
2093
|
+ FLOW_SPEC_TYPE_ICMP_TYPE: "icmp-type",
|
|
2094
|
+ FLOW_SPEC_TYPE_ICMP_CODE: "icmp-code",
|
|
2095
|
+ FLOW_SPEC_TYPE_TCP_FLAG: "tcp-flags",
|
|
2096
|
+ FLOW_SPEC_TYPE_PKT_LEN: "packet-length",
|
|
2097
|
+ FLOW_SPEC_TYPE_DSCP: "dscp",
|
|
2098
|
+ FLOW_SPEC_TYPE_FRAGMENT: "fragment",
|
|
2099
|
+ FLOW_SPEC_TYPE_LABEL: "label",
|
|
2100
|
+ FLOW_SPEC_TYPE_ETHERNET_TYPE: "ether-type",
|
|
2101
|
+ FLOW_SPEC_TYPE_SRC_MAC: "source-mac",
|
|
2102
|
+ FLOW_SPEC_TYPE_DST_MAC: "destination-mac",
|
|
2103
|
+ FLOW_SPEC_TYPE_LLC_DSAP: "llc-dsap",
|
|
2104
|
+ FLOW_SPEC_TYPE_LLC_SSAP: "llc-ssap",
|
|
2105
|
+ FLOW_SPEC_TYPE_LLC_CONTROL: "llc-control",
|
|
2106
|
+ FLOW_SPEC_TYPE_SNAP: "snap",
|
|
2107
|
+ FLOW_SPEC_TYPE_VID: "vid",
|
|
2108
|
+ FLOW_SPEC_TYPE_COS: "cos",
|
|
2109
|
+ FLOW_SPEC_TYPE_INNER_VID: "inner-vid",
|
|
2110
|
+ FLOW_SPEC_TYPE_INNER_COS: "inner-cos",
|
2059
|
2111
|
}
|
2060
|
2112
|
|
2061
|
2113
|
var FlowSpecValueMap = map[string]BGPFlowSpecType{
|
2062
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_DST_PREFIX]: FLOW_SPEC_TYPE_DST_PREFIX,
|
2063
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_PREFIX]: FLOW_SPEC_TYPE_SRC_PREFIX,
|
2064
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_IP_PROTO]: FLOW_SPEC_TYPE_IP_PROTO,
|
2065
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_PORT]: FLOW_SPEC_TYPE_PORT,
|
2066
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_DST_PORT]: FLOW_SPEC_TYPE_DST_PORT,
|
2067
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_PORT]: FLOW_SPEC_TYPE_SRC_PORT,
|
2068
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_ICMP_TYPE]: FLOW_SPEC_TYPE_ICMP_TYPE,
|
2069
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_ICMP_CODE]: FLOW_SPEC_TYPE_ICMP_CODE,
|
2070
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_TCP_FLAG]: FLOW_SPEC_TYPE_TCP_FLAG,
|
2071
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_PKT_LEN]: FLOW_SPEC_TYPE_PKT_LEN,
|
2072
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_DSCP]: FLOW_SPEC_TYPE_DSCP,
|
2073
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_FRAGMENT]: FLOW_SPEC_TYPE_FRAGMENT,
|
2074
|
|
- FlowSpecNameMap[FLOW_SPEC_TYPE_LABEL]: FLOW_SPEC_TYPE_LABEL,
|
|
2114
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_DST_PREFIX]: FLOW_SPEC_TYPE_DST_PREFIX,
|
|
2115
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_PREFIX]: FLOW_SPEC_TYPE_SRC_PREFIX,
|
|
2116
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_IP_PROTO]: FLOW_SPEC_TYPE_IP_PROTO,
|
|
2117
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_PORT]: FLOW_SPEC_TYPE_PORT,
|
|
2118
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_DST_PORT]: FLOW_SPEC_TYPE_DST_PORT,
|
|
2119
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_PORT]: FLOW_SPEC_TYPE_SRC_PORT,
|
|
2120
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_ICMP_TYPE]: FLOW_SPEC_TYPE_ICMP_TYPE,
|
|
2121
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_ICMP_CODE]: FLOW_SPEC_TYPE_ICMP_CODE,
|
|
2122
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_TCP_FLAG]: FLOW_SPEC_TYPE_TCP_FLAG,
|
|
2123
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_PKT_LEN]: FLOW_SPEC_TYPE_PKT_LEN,
|
|
2124
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_DSCP]: FLOW_SPEC_TYPE_DSCP,
|
|
2125
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_FRAGMENT]: FLOW_SPEC_TYPE_FRAGMENT,
|
|
2126
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_LABEL]: FLOW_SPEC_TYPE_LABEL,
|
|
2127
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_ETHERNET_TYPE]: FLOW_SPEC_TYPE_ETHERNET_TYPE,
|
|
2128
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_MAC]: FLOW_SPEC_TYPE_SRC_MAC,
|
|
2129
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_DST_MAC]: FLOW_SPEC_TYPE_DST_MAC,
|
|
2130
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_LLC_DSAP]: FLOW_SPEC_TYPE_LLC_DSAP,
|
|
2131
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_LLC_SSAP]: FLOW_SPEC_TYPE_LLC_SSAP,
|
|
2132
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_LLC_CONTROL]: FLOW_SPEC_TYPE_LLC_CONTROL,
|
|
2133
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_SNAP]: FLOW_SPEC_TYPE_SNAP,
|
|
2134
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_VID]: FLOW_SPEC_TYPE_VID,
|
|
2135
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_COS]: FLOW_SPEC_TYPE_COS,
|
|
2136
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_INNER_VID]: FLOW_SPEC_TYPE_INNER_VID,
|
|
2137
|
+ FlowSpecNameMap[FLOW_SPEC_TYPE_INNER_COS]: FLOW_SPEC_TYPE_INNER_COS,
|
2075
|
2138
|
}
|
2076
|
2139
|
|
2077
|
2140
|
func flowSpecPrefixParser(rf RouteFamily, args []string) (FlowSpecComponentInterface, error) {
|
|
@@ -2174,6 +2237,29 @@ func flowSpecTcpFlagParser(rf RouteFamily, args []string) (FlowSpecComponentInte
|
2174
|
2237
|
return NewFlowSpecComponent(FLOW_SPEC_TYPE_TCP_FLAG, items), nil
|
2175
|
2238
|
}
|
2176
|
2239
|
|
|
2240
|
+func flowSpecEtherTypeParser(rf RouteFamily, args []string) (FlowSpecComponentInterface, error) {
|
|
2241
|
+ ss := make([]string, 0, len(EthernetTypeNameMap))
|
|
2242
|
+ for _, v := range EthernetTypeNameMap {
|
|
2243
|
+ ss = append(ss, v)
|
|
2244
|
+ }
|
|
2245
|
+ protos := strings.Join(ss, "|")
|
|
2246
|
+ exp := regexp.MustCompile(fmt.Sprintf("^%s (((%s) )*)(%s)$", FlowSpecNameMap[FLOW_SPEC_TYPE_ETHERNET_TYPE], protos, protos))
|
|
2247
|
+ elems := exp.FindStringSubmatch(strings.Join(args, " "))
|
|
2248
|
+ items := make([]*FlowSpecComponentItem, 0)
|
|
2249
|
+ eq := 0x1
|
|
2250
|
+ if elems[1] != "" {
|
|
2251
|
+ for _, v := range strings.Split(elems[1], " ") {
|
|
2252
|
+ p, ok := EthernetTypeValueMap[v]
|
|
2253
|
+ if !ok {
|
|
2254
|
+ continue
|
|
2255
|
+ }
|
|
2256
|
+ items = append(items, NewFlowSpecComponentItem(eq, int(p)))
|
|
2257
|
+ }
|
|
2258
|
+ }
|
|
2259
|
+ items = append(items, NewFlowSpecComponentItem(eq, int(EthernetTypeValueMap[elems[4]])))
|
|
2260
|
+ return NewFlowSpecComponent(FLOW_SPEC_TYPE_ETHERNET_TYPE, items), nil
|
|
2261
|
+}
|
|
2262
|
+
|
2177
|
2263
|
func doFlowSpecNumericParser(rf RouteFamily, args []string, validationFunc func(int) error) (FlowSpecComponentInterface, error) {
|
2178
|
2264
|
if afi, _ := RouteFamilyToAfiSafi(rf); afi == AFI_IP && FlowSpecValueMap[args[0]] == FLOW_SPEC_TYPE_LABEL {
|
2179
|
2265
|
return nil, fmt.Errorf("flow label spec is only allowed for ipv6")
|
|
@@ -2265,40 +2351,77 @@ func flowSpecFragmentParser(rf RouteFamily, args []string) (FlowSpecComponentInt
|
2265
|
2351
|
if len(args) < 2 {
|
2266
|
2352
|
return nil, fmt.Errorf("invalid flowspec fragment specifier")
|
2267
|
2353
|
}
|
2268
|
|
- value := 0
|
2269
|
|
- switch args[1] {
|
2270
|
|
- case "not-a-fragment":
|
2271
|
|
- if afi, _ := RouteFamilyToAfiSafi(rf); afi == AFI_IP6 {
|
2272
|
|
- return nil, fmt.Errorf("can't specify not-a-fragment for ipv6")
|
|
2354
|
+ items := make([]*FlowSpecComponentItem, 0)
|
|
2355
|
+ for _, a := range args[1:] {
|
|
2356
|
+ value := 0
|
|
2357
|
+ switch a {
|
|
2358
|
+ case "dont-fragment":
|
|
2359
|
+ if afi, _ := RouteFamilyToAfiSafi(rf); afi == AFI_IP6 {
|
|
2360
|
+ return nil, fmt.Errorf("can't specify dont-fragment for ipv6")
|
|
2361
|
+ }
|
|
2362
|
+ value = 0x1
|
|
2363
|
+ case "is-fragment":
|
|
2364
|
+ value = 0x2
|
|
2365
|
+ case "first-fragment":
|
|
2366
|
+ value = 0x4
|
|
2367
|
+ case "last-fragment":
|
|
2368
|
+ value = 0x8
|
|
2369
|
+ case "not-a-fragment":
|
|
2370
|
+ value = 0x0
|
|
2371
|
+ default:
|
|
2372
|
+ return nil, fmt.Errorf("invalid flowspec fragment specifier")
|
2273
|
2373
|
}
|
2274
|
|
- value = 0x1
|
2275
|
|
- case "is-a-fragment":
|
2276
|
|
- value = 0x2
|
2277
|
|
- case "first-fragment":
|
2278
|
|
- value = 0x4
|
2279
|
|
- case "last-fragment":
|
2280
|
|
- value = 0x8
|
2281
|
|
- default:
|
2282
|
|
- return nil, fmt.Errorf("invalid flowspec fragment specifier")
|
|
2374
|
+ items = append(items, NewFlowSpecComponentItem(0, value))
|
2283
|
2375
|
}
|
2284
|
|
- items := []*FlowSpecComponentItem{NewFlowSpecComponentItem(0, value)}
|
2285
|
2376
|
return NewFlowSpecComponent(FlowSpecValueMap[args[0]], items), nil
|
2286
|
2377
|
}
|
2287
|
2378
|
|
|
2379
|
+func flowSpecMacParser(rf RouteFamily, args []string) (FlowSpecComponentInterface, error) {
|
|
2380
|
+ if len(args) < 2 {
|
|
2381
|
+ return nil, fmt.Errorf("invalid flowspec dst/src mac")
|
|
2382
|
+ }
|
|
2383
|
+ if rf != RF_FS_L2_VPN {
|
|
2384
|
+ return nil, fmt.Errorf("invalid family")
|
|
2385
|
+ }
|
|
2386
|
+ typ := args[0]
|
|
2387
|
+ mac, err := net.ParseMAC(args[1])
|
|
2388
|
+ if err != nil {
|
|
2389
|
+ return nil, fmt.Errorf("invalid mac")
|
|
2390
|
+ }
|
|
2391
|
+ switch typ {
|
|
2392
|
+ case FlowSpecNameMap[FLOW_SPEC_TYPE_DST_MAC]:
|
|
2393
|
+ return NewFlowSpecDestinationMac(mac), nil
|
|
2394
|
+ case FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_MAC]:
|
|
2395
|
+ return NewFlowSpecSourceMac(mac), nil
|
|
2396
|
+ }
|
|
2397
|
+ return nil, fmt.Errorf("invalid type. only %s or %s allowed", FlowSpecNameMap[FLOW_SPEC_TYPE_DST_MAC], FlowSpecNameMap[FLOW_SPEC_TYPE_SRC_MAC])
|
|
2398
|
+}
|
|
2399
|
+
|
2288
|
2400
|
var flowSpecParserMap = map[BGPFlowSpecType]func(RouteFamily, []string) (FlowSpecComponentInterface, error){
|
2289
|
|
- FLOW_SPEC_TYPE_DST_PREFIX: flowSpecPrefixParser,
|
2290
|
|
- FLOW_SPEC_TYPE_SRC_PREFIX: flowSpecPrefixParser,
|
2291
|
|
- FLOW_SPEC_TYPE_IP_PROTO: flowSpecIpProtoParser,
|
2292
|
|
- FLOW_SPEC_TYPE_PORT: flowSpecPortParser,
|
2293
|
|
- FLOW_SPEC_TYPE_DST_PORT: flowSpecPortParser,
|
2294
|
|
- FLOW_SPEC_TYPE_SRC_PORT: flowSpecPortParser,
|
2295
|
|
- FLOW_SPEC_TYPE_ICMP_TYPE: flowSpecNumericParser,
|
2296
|
|
- FLOW_SPEC_TYPE_ICMP_CODE: flowSpecNumericParser,
|
2297
|
|
- FLOW_SPEC_TYPE_TCP_FLAG: flowSpecTcpFlagParser,
|
2298
|
|
- FLOW_SPEC_TYPE_PKT_LEN: flowSpecNumericParser,
|
2299
|
|
- FLOW_SPEC_TYPE_DSCP: flowSpecDscpParser,
|
2300
|
|
- FLOW_SPEC_TYPE_FRAGMENT: flowSpecFragmentParser,
|
2301
|
|
- FLOW_SPEC_TYPE_LABEL: flowSpecNumericParser,
|
|
2401
|
+ FLOW_SPEC_TYPE_DST_PREFIX: flowSpecPrefixParser,
|
|
2402
|
+ FLOW_SPEC_TYPE_SRC_PREFIX: flowSpecPrefixParser,
|
|
2403
|
+ FLOW_SPEC_TYPE_IP_PROTO: flowSpecIpProtoParser,
|
|
2404
|
+ FLOW_SPEC_TYPE_PORT: flowSpecPortParser,
|
|
2405
|
+ FLOW_SPEC_TYPE_DST_PORT: flowSpecPortParser,
|
|
2406
|
+ FLOW_SPEC_TYPE_SRC_PORT: flowSpecPortParser,
|
|
2407
|
+ FLOW_SPEC_TYPE_ICMP_TYPE: flowSpecNumericParser,
|
|
2408
|
+ FLOW_SPEC_TYPE_ICMP_CODE: flowSpecNumericParser,
|
|
2409
|
+ FLOW_SPEC_TYPE_TCP_FLAG: flowSpecTcpFlagParser,
|
|
2410
|
+ FLOW_SPEC_TYPE_PKT_LEN: flowSpecNumericParser,
|
|
2411
|
+ FLOW_SPEC_TYPE_DSCP: flowSpecDscpParser,
|
|
2412
|
+ FLOW_SPEC_TYPE_FRAGMENT: flowSpecFragmentParser,
|
|
2413
|
+ FLOW_SPEC_TYPE_LABEL: flowSpecNumericParser,
|
|
2414
|
+ FLOW_SPEC_TYPE_ETHERNET_TYPE: flowSpecEtherTypeParser,
|
|
2415
|
+ FLOW_SPEC_TYPE_DST_MAC: flowSpecMacParser,
|
|
2416
|
+ FLOW_SPEC_TYPE_SRC_MAC: flowSpecMacParser,
|
|
2417
|
+ FLOW_SPEC_TYPE_LLC_DSAP: flowSpecNumericParser,
|
|
2418
|
+ FLOW_SPEC_TYPE_LLC_SSAP: flowSpecNumericParser,
|
|
2419
|
+ FLOW_SPEC_TYPE_LLC_CONTROL: flowSpecNumericParser,
|
|
2420
|
+ FLOW_SPEC_TYPE_SNAP: flowSpecNumericParser,
|
|
2421
|
+ FLOW_SPEC_TYPE_VID: flowSpecNumericParser,
|
|
2422
|
+ FLOW_SPEC_TYPE_COS: flowSpecNumericParser,
|
|
2423
|
+ FLOW_SPEC_TYPE_INNER_VID: flowSpecNumericParser,
|
|
2424
|
+ FLOW_SPEC_TYPE_INNER_COS: flowSpecNumericParser,
|
2302
|
2425
|
}
|
2303
|
2426
|
|
2304
|
2427
|
func ParseFlowSpecComponents(rf RouteFamily, input string) ([]FlowSpecComponentInterface, error) {
|
|
@@ -2477,47 +2600,122 @@ func NewFlowSpecSourcePrefix6(prefix AddrPrefixInterface, offset uint8) *FlowSpe
|
2477
|
2600
|
return &FlowSpecSourcePrefix6{flowSpecPrefix6{prefix, offset, FLOW_SPEC_TYPE_SRC_PREFIX}}
|
2478
|
2601
|
}
|
2479
|
2602
|
|
|
2603
|
+type flowSpecMac struct {
|
|
2604
|
+ Mac net.HardwareAddr
|
|
2605
|
+ type_ BGPFlowSpecType
|
|
2606
|
+}
|
|
2607
|
+
|
|
2608
|
+func (p *flowSpecMac) DecodeFromBytes(data []byte) error {
|
|
2609
|
+ if len(data) < 2 || len(data) < 2+int(data[1]) {
|
|
2610
|
+ return fmt.Errorf("not all mac bits available")
|
|
2611
|
+ }
|
|
2612
|
+ p.type_ = BGPFlowSpecType(data[0])
|
|
2613
|
+ p.Mac = net.HardwareAddr(data[2 : 2+int(data[1])])
|
|
2614
|
+ return nil
|
|
2615
|
+}
|
|
2616
|
+
|
|
2617
|
+func (p *flowSpecMac) Serialize() ([]byte, error) {
|
|
2618
|
+ if len(p.Mac) == 0 {
|
|
2619
|
+ return nil, fmt.Errorf("mac unset")
|
|
2620
|
+ }
|
|
2621
|
+ buf := []byte{byte(p.Type()), byte(len(p.Mac))}
|
|
2622
|
+ return append(buf, []byte(p.Mac)...), nil
|
|
2623
|
+}
|
|
2624
|
+
|
|
2625
|
+func (p *flowSpecMac) Len() int {
|
|
2626
|
+ return 2 + len(p.Mac)
|
|
2627
|
+}
|
|
2628
|
+
|
|
2629
|
+func (p *flowSpecMac) Type() BGPFlowSpecType {
|
|
2630
|
+ return p.type_
|
|
2631
|
+}
|
|
2632
|
+
|
|
2633
|
+func (p *flowSpecMac) String() string {
|
|
2634
|
+ return fmt.Sprintf("[%s:%s]", p.Type(), p.Mac.String())
|
|
2635
|
+}
|
|
2636
|
+
|
|
2637
|
+func (p *flowSpecMac) MarshalJSON() ([]byte, error) {
|
|
2638
|
+ return json.Marshal(struct {
|
|
2639
|
+ Type BGPFlowSpecType `json:"type"`
|
|
2640
|
+ Value string `json:"value"`
|
|
2641
|
+ }{
|
|
2642
|
+ Type: p.Type(),
|
|
2643
|
+ Value: p.Mac.String(),
|
|
2644
|
+ })
|
|
2645
|
+}
|
|
2646
|
+
|
|
2647
|
+type FlowSpecSourceMac struct {
|
|
2648
|
+ flowSpecMac
|
|
2649
|
+}
|
|
2650
|
+
|
|
2651
|
+func NewFlowSpecSourceMac(mac net.HardwareAddr) *FlowSpecSourceMac {
|
|
2652
|
+ return &FlowSpecSourceMac{flowSpecMac{Mac: mac, type_: FLOW_SPEC_TYPE_SRC_MAC}}
|
|
2653
|
+}
|
|
2654
|
+
|
|
2655
|
+type FlowSpecDestinationMac struct {
|
|
2656
|
+ flowSpecMac
|
|
2657
|
+}
|
|
2658
|
+
|
|
2659
|
+func NewFlowSpecDestinationMac(mac net.HardwareAddr) *FlowSpecDestinationMac {
|
|
2660
|
+ return &FlowSpecDestinationMac{flowSpecMac{Mac: mac, type_: FLOW_SPEC_TYPE_DST_MAC}}
|
|
2661
|
+}
|
|
2662
|
+
|
2480
|
2663
|
type FlowSpecComponentItem struct {
|
2481
|
2664
|
Op int `json:"op"`
|
2482
|
2665
|
Value int `json:"value"`
|
2483
|
2666
|
}
|
2484
|
2667
|
|
|
2668
|
+func (v *FlowSpecComponentItem) Len() int {
|
|
2669
|
+ return 1 << ((uint32(v.Op) >> 4) & 0x3)
|
|
2670
|
+}
|
|
2671
|
+
|
2485
|
2672
|
func (v *FlowSpecComponentItem) Serialize() ([]byte, error) {
|
2486
|
2673
|
if v.Value < 0 {
|
2487
|
2674
|
return nil, fmt.Errorf("invalid value size(too small): %d", v.Value)
|
2488
|
2675
|
}
|
2489
|
2676
|
if v.Op < 0 || v.Op > math.MaxUint8 {
|
2490
|
2677
|
return nil, fmt.Errorf("invalid op size: %d", v.Op)
|
2491
|
|
- }
|
2492
|
2678
|
|
2493
|
|
- for i := 0; i < 3; i++ {
|
2494
|
|
- if v.Value < (1 << ((1 << uint(i)) * 8)) {
|
2495
|
|
- buf := make([]byte, 1+(1<<uint(i)))
|
2496
|
|
- switch i {
|
2497
|
|
- case 0:
|
2498
|
|
- buf[1] = byte(v.Value)
|
2499
|
|
- v.Op &^= 0x30
|
2500
|
|
- case 1:
|
2501
|
|
- binary.BigEndian.PutUint16(buf[1:], uint16(v.Value))
|
2502
|
|
- v.Op |= 0x10
|
2503
|
|
- v.Op &^= 0x20
|
2504
|
|
- case 2:
|
2505
|
|
- binary.BigEndian.PutUint32(buf[1:], uint32(v.Value))
|
2506
|
|
- v.Op &^= 0x10
|
2507
|
|
- v.Op |= 0x20
|
2508
|
|
- case 3:
|
2509
|
|
- binary.BigEndian.PutUint64(buf[1:], uint64(v.Value))
|
2510
|
|
- v.Op |= 0x30
|
2511
|
|
- }
|
2512
|
|
- buf[0] = byte(v.Op)
|
2513
|
|
- return buf, nil
|
2514
|
|
- }
|
2515
|
2679
|
}
|
2516
|
|
- return nil, fmt.Errorf("invalid value size(too big): %d", v.Value)
|
|
2680
|
+ order := uint32(math.Log2(float64(v.Len())))
|
|
2681
|
+ buf := make([]byte, 1+(1<<order))
|
|
2682
|
+ buf[0] = byte(uint32(v.Op) | order<<4)
|
|
2683
|
+ switch order {
|
|
2684
|
+ case 0:
|
|
2685
|
+ buf[1] = byte(v.Value)
|
|
2686
|
+ case 1:
|
|
2687
|
+ binary.BigEndian.PutUint16(buf[1:], uint16(v.Value))
|
|
2688
|
+ case 2:
|
|
2689
|
+ binary.BigEndian.PutUint32(buf[1:], uint32(v.Value))
|
|
2690
|
+ case 3:
|
|
2691
|
+ binary.BigEndian.PutUint64(buf[1:], uint64(v.Value))
|
|
2692
|
+ default:
|
|
2693
|
+ return nil, fmt.Errorf("invalid value size(too big): %d", v.Value)
|
|
2694
|
+ }
|
|
2695
|
+ return buf, nil
|
2517
|
2696
|
}
|
2518
|
2697
|
|
2519
|
2698
|
func NewFlowSpecComponentItem(op int, value int) *FlowSpecComponentItem {
|
2520
|
|
- return &FlowSpecComponentItem{op, value}
|
|
2699
|
+ v := &FlowSpecComponentItem{op, value}
|
|
2700
|
+ order := uint32(math.Log2(float64(v.Len())))
|
|
2701
|
+ // we don't know if not initialized properly or initialized to
|
|
2702
|
+ // zero...
|
|
2703
|
+ if order == 0 {
|
|
2704
|
+ order = func() uint32 {
|
|
2705
|
+ for i := 0; i < 3; i++ {
|
|
2706
|
+ if v.Value < (1 << ((1 << uint(i)) * 8)) {
|
|
2707
|
+ return uint32(i)
|
|
2708
|
+ }
|
|
2709
|
+ }
|
|
2710
|
+ // return invalid order
|
|
2711
|
+ return 4
|
|
2712
|
+ }()
|
|
2713
|
+ }
|
|
2714
|
+ if order > 3 {
|
|
2715
|
+ return nil
|
|
2716
|
+ }
|
|
2717
|
+ v.Op = int(uint32(v.Op) | order<<4)
|
|
2718
|
+ return v
|
2521
|
2719
|
}
|
2522
|
2720
|
|
2523
|
2721
|
type FlowSpecComponent struct {
|
|
@@ -2568,8 +2766,11 @@ func (p *FlowSpecComponent) Serialize() ([]byte, error) {
|
2568
|
2766
|
}
|
2569
|
2767
|
|
2570
|
2768
|
func (p *FlowSpecComponent) Len() int {
|
2571
|
|
- buf, _ := p.Serialize()
|
2572
|
|
- return len(buf)
|
|
2769
|
+ l := 1
|
|
2770
|
+ for _, item := range p.Items {
|
|
2771
|
+ l += (item.Len() + 1)
|
|
2772
|
+ }
|
|
2773
|
+ return l
|
2573
|
2774
|
}
|
2574
|
2775
|
|
2575
|
2776
|
func (p *FlowSpecComponent) Type() BGPFlowSpecType {
|
|
@@ -2626,12 +2827,15 @@ func formatFlag(op int, value int) string {
|
2626
|
2827
|
}
|
2627
|
2828
|
|
2628
|
2829
|
func formatFragment(op int, value int) string {
|
2629
|
|
- ss := make([]string, 0, 4)
|
2630
|
|
- if value&0x1 > 0 {
|
|
2830
|
+ ss := make([]string, 0)
|
|
2831
|
+ if value == 0 {
|
2631
|
2832
|
ss = append(ss, "not-a-fragment")
|
2632
|
2833
|
}
|
|
2834
|
+ if value&0x1 > 0 {
|
|
2835
|
+ ss = append(ss, "dont-fragment")
|
|
2836
|
+ }
|
2633
|
2837
|
if value&0x2 > 0 {
|
2634
|
|
- ss = append(ss, "is-a-fragment")
|
|
2838
|
+ ss = append(ss, "is-fragment")
|
2635
|
2839
|
}
|
2636
|
2840
|
if value&0x4 > 0 {
|
2637
|
2841
|
ss = append(ss, "first-fragment")
|
|
@@ -2645,27 +2849,39 @@ func formatFragment(op int, value int) string {
|
2645
|
2849
|
return fmt.Sprintf("%s%s", formatNumericOp(op), ss[0])
|
2646
|
2850
|
}
|
2647
|
2851
|
|
|
2852
|
+func formatEtherType(op int, value int) string {
|
|
2853
|
+ return fmt.Sprintf(" %s", EthernetType(value).String())
|
|
2854
|
+}
|
|
2855
|
+
|
2648
|
2856
|
var flowSpecFormatMap = map[BGPFlowSpecType]func(op int, value int) string{
|
2649
|
|
- FLOW_SPEC_TYPE_UNKNOWN: formatRaw,
|
2650
|
|
- FLOW_SPEC_TYPE_IP_PROTO: formatProto,
|
2651
|
|
- FLOW_SPEC_TYPE_PORT: formatNumeric,
|
2652
|
|
- FLOW_SPEC_TYPE_DST_PORT: formatNumeric,
|
2653
|
|
- FLOW_SPEC_TYPE_SRC_PORT: formatNumeric,
|
2654
|
|
- FLOW_SPEC_TYPE_ICMP_TYPE: formatNumeric,
|
2655
|
|
- FLOW_SPEC_TYPE_ICMP_CODE: formatNumeric,
|
2656
|
|
- FLOW_SPEC_TYPE_TCP_FLAG: formatFlag,
|
2657
|
|
- FLOW_SPEC_TYPE_PKT_LEN: formatNumeric,
|
2658
|
|
- FLOW_SPEC_TYPE_DSCP: formatNumeric,
|
2659
|
|
- FLOW_SPEC_TYPE_FRAGMENT: formatFragment,
|
2660
|
|
- FLOW_SPEC_TYPE_LABEL: formatNumeric,
|
|
2857
|
+ FLOW_SPEC_TYPE_UNKNOWN: formatRaw,
|
|
2858
|
+ FLOW_SPEC_TYPE_IP_PROTO: formatProto,
|
|
2859
|
+ FLOW_SPEC_TYPE_PORT: formatNumeric,
|
|
2860
|
+ FLOW_SPEC_TYPE_DST_PORT: formatNumeric,
|
|
2861
|
+ FLOW_SPEC_TYPE_SRC_PORT: formatNumeric,
|
|
2862
|
+ FLOW_SPEC_TYPE_ICMP_TYPE: formatNumeric,
|
|
2863
|
+ FLOW_SPEC_TYPE_ICMP_CODE: formatNumeric,
|
|
2864
|
+ FLOW_SPEC_TYPE_TCP_FLAG: formatFlag,
|
|
2865
|
+ FLOW_SPEC_TYPE_PKT_LEN: formatNumeric,
|
|
2866
|
+ FLOW_SPEC_TYPE_DSCP: formatNumeric,
|
|
2867
|
+ FLOW_SPEC_TYPE_FRAGMENT: formatFragment,
|
|
2868
|
+ FLOW_SPEC_TYPE_LABEL: formatNumeric,
|
|
2869
|
+ FLOW_SPEC_TYPE_ETHERNET_TYPE: formatEtherType,
|
|
2870
|
+ FLOW_SPEC_TYPE_LLC_DSAP: formatNumeric,
|
|
2871
|
+ FLOW_SPEC_TYPE_LLC_SSAP: formatNumeric,
|
|
2872
|
+ FLOW_SPEC_TYPE_LLC_CONTROL: formatNumeric,
|
|
2873
|
+ FLOW_SPEC_TYPE_SNAP: formatNumeric,
|
|
2874
|
+ FLOW_SPEC_TYPE_VID: formatNumeric,
|
|
2875
|
+ FLOW_SPEC_TYPE_COS: formatNumeric,
|
|
2876
|
+ FLOW_SPEC_TYPE_INNER_VID: formatNumeric,
|
|
2877
|
+ FLOW_SPEC_TYPE_INNER_COS: formatNumeric,
|
2661
|
2878
|
}
|
2662
|
2879
|
|
2663
|
2880
|
func (p *FlowSpecComponent) String() string {
|
2664
|
|
- var f func(op int, value int) string
|
2665
|
|
- if _, ok := flowSpecFormatMap[p.Type()]; !ok {
|
2666
|
|
- f = flowSpecFormatMap[FLOW_SPEC_TYPE_UNKNOWN]
|
|
2881
|
+ f := flowSpecFormatMap[FLOW_SPEC_TYPE_UNKNOWN]
|
|
2882
|
+ if _, ok := flowSpecFormatMap[p.Type()]; ok {
|
|
2883
|
+ f = flowSpecFormatMap[p.Type()]
|
2667
|
2884
|
}
|
2668
|
|
- f = flowSpecFormatMap[p.Type()]
|
2669
|
2885
|
buf := bytes.NewBuffer(make([]byte, 0, 32))
|
2670
|
2886
|
for _, i := range p.Items {
|
2671
|
2887
|
buf.WriteString(f(i.Op, i.Value))
|
|
@@ -2725,17 +2941,22 @@ type FlowSpecNLRI struct {
|
2725
|
2941
|
|
2726
|
2942
|
func (n *FlowSpecNLRI) decodeFromBytes(rf RouteFamily, data []byte) error {
|
2727
|
2943
|
var length int
|
2728
|
|
- if (data[0] >> 4) == 0xf {
|
|
2944
|
+ if (data[0]>>4) == 0xf && len(data) > 2 {
|
2729
|
2945
|
length = int(binary.BigEndian.Uint16(data[0:2]))
|
2730
|
2946
|
data = data[2:]
|
2731
|
|
- } else {
|
|
2947
|
+ } else if len(data) > 1 {
|
2732
|
2948
|
length = int(data[0])
|
2733
|
2949
|
data = data[1:]
|
|
2950
|
+ } else {
|
|
2951
|
+ return fmt.Errorf("not all flowspec component bytes available")
|
2734
|
2952
|
}
|
2735
|
2953
|
|
2736
|
2954
|
n.rf = rf
|
2737
|
2955
|
|
2738
|
2956
|
for l := length; l > 0; {
|
|
2957
|
+ if len(data) == 0 {
|
|
2958
|
+ return fmt.Errorf("not all flowspec component bytes available")
|
|
2959
|
+ }
|
2739
|
2960
|
t := BGPFlowSpecType(data[0])
|
2740
|
2961
|
var i FlowSpecComponentInterface
|
2741
|
2962
|
switch t {
|
|
@@ -2765,9 +2986,25 @@ func (n *FlowSpecNLRI) decodeFromBytes(rf RouteFamily, data []byte) error {
|
2765
|
2986
|
default:
|
2766
|
2987
|
return fmt.Errorf("Invalid RF: %v", rf)
|
2767
|
2988
|
}
|
|
2989
|
+ case FLOW_SPEC_TYPE_SRC_MAC:
|
|
2990
|
+ switch rf {
|
|
2991
|
+ case RF_FS_L2_VPN:
|
|
2992
|
+ i = NewFlowSpecSourceMac(nil)
|
|
2993
|
+ default:
|
|
2994
|
+ return fmt.Errorf("invalid family: %v", rf)
|
|
2995
|
+ }
|
|
2996
|
+ case FLOW_SPEC_TYPE_DST_MAC:
|
|
2997
|
+ switch rf {
|
|
2998
|
+ case RF_FS_L2_VPN:
|
|
2999
|
+ i = NewFlowSpecDestinationMac(nil)
|
|
3000
|
+ default:
|
|
3001
|
+ return fmt.Errorf("invalid family: %v", rf)
|
|
3002
|
+ }
|
2768
|
3003
|
case FLOW_SPEC_TYPE_IP_PROTO, FLOW_SPEC_TYPE_PORT, FLOW_SPEC_TYPE_DST_PORT, FLOW_SPEC_TYPE_SRC_PORT,
|
2769
|
3004
|
FLOW_SPEC_TYPE_ICMP_TYPE, FLOW_SPEC_TYPE_ICMP_CODE, FLOW_SPEC_TYPE_TCP_FLAG, FLOW_SPEC_TYPE_PKT_LEN,
|
2770
|
|
- FLOW_SPEC_TYPE_DSCP, FLOW_SPEC_TYPE_FRAGMENT, FLOW_SPEC_TYPE_LABEL:
|
|
3005
|
+ FLOW_SPEC_TYPE_DSCP, FLOW_SPEC_TYPE_FRAGMENT, FLOW_SPEC_TYPE_LABEL, FLOW_SPEC_TYPE_ETHERNET_TYPE,
|
|
3006
|
+ FLOW_SPEC_TYPE_LLC_DSAP, FLOW_SPEC_TYPE_LLC_SSAP, FLOW_SPEC_TYPE_LLC_CONTROL, FLOW_SPEC_TYPE_SNAP,
|
|
3007
|
+ FLOW_SPEC_TYPE_VID, FLOW_SPEC_TYPE_COS, FLOW_SPEC_TYPE_INNER_VID, FLOW_SPEC_TYPE_INNER_COS:
|
2771
|
3008
|
i = NewFlowSpecComponent(t, nil)
|
2772
|
3009
|
default:
|
2773
|
3010
|
i = &FlowSpecUnknown{}
|
|
@@ -2924,6 +3161,80 @@ func NewFlowSpecIPv6VPN(value []FlowSpecComponentInterface) *FlowSpecIPv6VPN {
|
2924
|
3161
|
}}
|
2925
|
3162
|
}
|
2926
|
3163
|
|
|
3164
|
+type FlowSpecL2VPN struct {
|
|
3165
|
+ FlowSpecNLRI
|
|
3166
|
+}
|
|
3167
|
+
|
|
3168
|
+func (n *FlowSpecL2VPN) DecodeFromBytes(data []byte) error {
|
|
3169
|
+ return n.decodeFromBytes(AfiSafiToRouteFamily(n.AFI(), n.SAFI()), data)
|
|
3170
|
+}
|
|
3171
|
+
|
|
3172
|
+func (n *FlowSpecL2VPN) AFI() uint16 {
|
|
3173
|
+ return AFI_L2VPN
|
|
3174
|
+}
|
|
3175
|
+
|
|
3176
|
+func (n *FlowSpecL2VPN) SAFI() uint8 {
|
|
3177
|
+ return SAFI_FLOW_SPEC_VPN
|
|
3178
|
+}
|
|
3179
|
+
|
|
3180
|
+func NewFlowSpecL2VPN(value []FlowSpecComponentInterface) *FlowSpecL2VPN {
|
|
3181
|
+ return &FlowSpecL2VPN{FlowSpecNLRI{
|
|
3182
|
+ Value: value,
|
|
3183
|
+ rf: RF_FS_L2_VPN,
|
|
3184
|
+ }}
|
|
3185
|
+}
|
|
3186
|
+
|
|
3187
|
+type OpaqueNLRI struct {
|
|
3188
|
+ Length uint8
|
|
3189
|
+ Key []byte
|
|
3190
|
+}
|
|
3191
|
+
|
|
3192
|
+func (n *OpaqueNLRI) DecodeFromBytes(data []byte) error {
|
|
3193
|
+ n.Length = data[0]
|
|
3194
|
+ if len(data)-1 < int(n.Length) {
|
|
3195
|
+ return fmt.Errorf("Not all OpaqueNLRI bytes available")
|
|
3196
|
+ }
|
|
3197
|
+ n.Key = data[1 : 1+n.Length]
|
|
3198
|
+ return nil
|
|
3199
|
+}
|
|
3200
|
+
|
|
3201
|
+func (n *OpaqueNLRI) Serialize() ([]byte, error) {
|
|
3202
|
+ if len(n.Key) > math.MaxUint8 {
|
|
3203
|
+ return nil, fmt.Errorf("Key length too big")
|
|
3204
|
+ }
|
|
3205
|
+ return append([]byte{byte(len(n.Key))}, n.Key...), nil
|
|
3206
|
+}
|
|
3207
|
+
|
|
3208
|
+func (n *OpaqueNLRI) AFI() uint16 {
|
|
3209
|
+ return AFI_OPAQUE
|
|
3210
|
+}
|
|
3211
|
+
|
|
3212
|
+func (n *OpaqueNLRI) SAFI() uint8 {
|
|
3213
|
+ return SAFI_KEY_VALUE
|
|
3214
|
+}
|
|
3215
|
+
|
|
3216
|
+func (n *OpaqueNLRI) Len() int {
|
|
3217
|
+ return 1 + len(n.Key)
|
|
3218
|
+}
|
|
3219
|
+
|
|
3220
|
+func (n *OpaqueNLRI) String() string {
|
|
3221
|
+ return string(n.Key)
|
|
3222
|
+}
|
|
3223
|
+
|
|
3224
|
+func (n *OpaqueNLRI) MarshalJSON() ([]byte, error) {
|
|
3225
|
+ return json.Marshal(struct {
|
|
3226
|
+ Key string `json:"key"`
|
|
3227
|
+ }{
|
|
3228
|
+ Key: n.String(),
|
|
3229
|
+ })
|
|
3230
|
+}
|
|
3231
|
+
|
|
3232
|
+func NewOpaqueNLRI(key []byte) *OpaqueNLRI {
|
|
3233
|
+ return &OpaqueNLRI{
|
|
3234
|
+ Key: key,
|
|
3235
|
+ }
|
|
3236
|
+}
|
|
3237
|
+
|
2927
|
3238
|
func AfiSafiToRouteFamily(afi uint16, safi uint8) RouteFamily {
|
2928
|
3239
|
return RouteFamily(int(afi)<<16 | int(safi))
|
2929
|
3240
|
}
|
|
@@ -2934,6 +3245,13 @@ func RouteFamilyToAfiSafi(rf RouteFamily) (uint16, uint8) {
|
2934
|
3245
|
|
2935
|
3246
|
type RouteFamily int
|
2936
|
3247
|
|
|
3248
|
+func (f RouteFamily) String() string {
|
|
3249
|
+ if n, y := AddressFamilyNameMap[f]; y {
|
|
3250
|
+ return n
|
|
3251
|
+ }
|
|
3252
|
+ return fmt.Sprintf("UnknownFamily(%d)", f)
|
|
3253
|
+}
|
|
3254
|
+
|
2937
|
3255
|
const (
|
2938
|
3256
|
RF_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_UNICAST
|
2939
|
3257
|
RF_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_UNICAST
|
|
@@ -2953,6 +3271,8 @@ const (
|
2953
|
3271
|
RF_FS_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_VPN
|
2954
|
3272
|
RF_FS_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_UNICAST
|
2955
|
3273
|
RF_FS_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_VPN
|
|
3274
|
+ RF_FS_L2_VPN RouteFamily = AFI_L2VPN<<16 | SAFI_FLOW_SPEC_VPN
|
|
3275
|
+ RF_OPAQUE RouteFamily = AFI_OPAQUE<<16 | SAFI_KEY_VALUE
|
2956
|
3276
|
)
|
2957
|
3277
|
|
2958
|
3278
|
var AddressFamilyNameMap = map[RouteFamily]string{
|
|
@@ -2974,6 +3294,8 @@ var AddressFamilyNameMap = map[RouteFamily]string{
|
2974
|
3294
|
RF_FS_IPv4_VPN: "l3vpn-ipv4-flowspec",
|
2975
|
3295
|
RF_FS_IPv6_UC: "ipv6-flowspec",
|
2976
|
3296
|
RF_FS_IPv6_VPN: "l3vpn-ipv6-flowspec",
|
|
3297
|
+ RF_FS_L2_VPN: "l2vpn-flowspec",
|
|
3298
|
+ RF_OPAQUE: "opaque",
|
2977
|
3299
|
}
|
2978
|
3300
|
|
2979
|
3301
|
var AddressFamilyValueMap = map[string]RouteFamily{
|
|
@@ -2995,6 +3317,8 @@ var AddressFamilyValueMap = map[string]RouteFamily{
|
2995
|
3317
|
AddressFamilyNameMap[RF_FS_IPv4_VPN]: RF_FS_IPv4_VPN,
|
2996
|
3318
|
AddressFamilyNameMap[RF_FS_IPv6_UC]: RF_FS_IPv6_UC,
|
2997
|
3319
|
AddressFamilyNameMap[RF_FS_IPv6_VPN]: RF_FS_IPv6_VPN,
|
|
3320
|
+ AddressFamilyNameMap[RF_FS_L2_VPN]: RF_FS_L2_VPN,
|
|
3321
|
+ AddressFamilyNameMap[RF_OPAQUE]: RF_OPAQUE,
|
2998
|
3322
|
}
|
2999
|
3323
|
|
3000
|
3324
|
func GetRouteFamily(name string) (RouteFamily, error) {
|
|
@@ -3032,6 +3356,10 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8) (prefix AddrPrefixInterfac
|
3032
|
3356
|
prefix = &FlowSpecIPv6Unicast{}
|
3033
|
3357
|
case RF_FS_IPv6_VPN:
|
3034
|
3358
|
prefix = &FlowSpecIPv6VPN{}
|
|
3359
|
+ case RF_FS_L2_VPN:
|
|
3360
|
+ prefix = &FlowSpecL2VPN{}
|
|
3361
|
+ case RF_OPAQUE:
|
|
3362
|
+ prefix = &OpaqueNLRI{}
|
3035
|
3363
|
default:
|
3036
|
3364
|
return nil, fmt.Errorf("unknown route family. AFI: %d, SAFI: %d", afi, safi)
|
3037
|
3365
|
}
|
|
@@ -3093,7 +3421,8 @@ const (
|
3093
|
3421
|
BGP_ATTR_TYPE_TUNNEL_ENCAP
|
3094
|
3422
|
_
|
3095
|
3423
|
_
|
3096
|
|
- BGP_ATTR_TYPE_AIGP // = 26
|
|
3424
|
+ BGP_ATTR_TYPE_AIGP // = 26
|
|
3425
|
+ BGP_ATTR_TYPE_OPAQUE_VALUE BGPAttrType = 41
|
3097
|
3426
|
)
|
3098
|
3427
|
|
3099
|
3428
|
// NOTIFICATION Error Code RFC 4271 4.5.
|
|
@@ -3186,6 +3515,7 @@ var pathAttrFlags map[BGPAttrType]BGPAttrFlag = map[BGPAttrType]BGPAttrFlag{
|
3186
|
3515
|
BGP_ATTR_TYPE_PMSI_TUNNEL: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL,
|
3187
|
3516
|
BGP_ATTR_TYPE_TUNNEL_ENCAP: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL,
|
3188
|
3517
|
BGP_ATTR_TYPE_AIGP: BGP_ATTR_FLAG_OPTIONAL,
|
|
3518
|
+ BGP_ATTR_TYPE_OPAQUE_VALUE: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL,
|
3189
|
3519
|
}
|
3190
|
3520
|
|
3191
|
3521
|
type PathAttributeInterface interface {
|
|
@@ -5246,7 +5576,7 @@ func parseFlowSpecExtended(data []byte) (ExtendedCommunityInterface, error) {
|
5246
|
5576
|
sample := (data[7]>>1)&0x1 == 1
|
5247
|
5577
|
return NewTrafficActionExtended(terminal, sample), nil
|
5248
|
5578
|
case EC_SUBTYPE_FLOWSPEC_REDIRECT:
|
5249
|
|
- //draft-ietf-idr-flowspec-redirect-rt-bis-05
|
|
5579
|
+ // RFC7674
|
5250
|
5580
|
switch typ {
|
5251
|
5581
|
case EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL:
|
5252
|
5582
|
as := binary.BigEndian.Uint16(data[2:4])
|
|
@@ -6030,6 +6360,35 @@ func NewPathAttributeAigp(values []AigpTLV) *PathAttributeAigp {
|
6030
|
6360
|
}
|
6031
|
6361
|
}
|
6032
|
6362
|
|
|
6363
|
+type PathAttributeOpaqueValue struct {
|
|
6364
|
+ PathAttribute
|
|
6365
|
+}
|
|
6366
|
+
|
|
6367
|
+func (p *PathAttributeOpaqueValue) String() string {
|
|
6368
|
+ return fmt.Sprintf("{Value: %s}", string(p.Value))
|
|
6369
|
+}
|
|
6370
|
+
|
|
6371
|
+func (p *PathAttributeOpaqueValue) MarshalJSON() ([]byte, error) {
|
|
6372
|
+ return json.Marshal(struct {
|
|
6373
|
+ Type BGPAttrType `json:"type"`
|
|
6374
|
+ Value string `json:"value"`
|
|
6375
|
+ }{
|
|
6376
|
+ Type: p.GetType(),
|
|
6377
|
+ Value: string(p.Value),
|
|
6378
|
+ })
|
|
6379
|
+}
|
|
6380
|
+
|
|
6381
|
+func NewPathAttributeOpaqueValue(value []byte) *PathAttributeOpaqueValue {
|
|
6382
|
+ t := BGP_ATTR_TYPE_OPAQUE_VALUE
|
|
6383
|
+ return &PathAttributeOpaqueValue{
|
|
6384
|
+ PathAttribute: PathAttribute{
|
|
6385
|
+ Flags: pathAttrFlags[t],
|
|
6386
|
+ Type: t,
|
|
6387
|
+ Value: value,
|
|
6388
|
+ },
|
|
6389
|
+ }
|
|
6390
|
+}
|
|
6391
|
+
|
6033
|
6392
|
type PathAttributeUnknown struct {
|
6034
|
6393
|
PathAttribute
|
6035
|
6394
|
}
|
|
@@ -6077,6 +6436,8 @@ func GetPathAttribute(data []byte) (PathAttributeInterface, error) {
|
6077
|
6436
|
return &PathAttributePmsiTunnel{}, nil
|
6078
|
6437
|
case BGP_ATTR_TYPE_AIGP:
|
6079
|
6438
|
return &PathAttributeAigp{}, nil
|
|
6439
|
+ case BGP_ATTR_TYPE_OPAQUE_VALUE:
|
|
6440
|
+ return &PathAttributeOpaqueValue{}, nil
|
6080
|
6441
|
}
|
6081
|
6442
|
return &PathAttributeUnknown{}, nil
|
6082
|
6443
|
}
|