go.ligato.io/vpp-agent/v3@v3.5.0/plugins/vpp/natplugin/vppcalls/vpp2101/dump_nat_vppcalls.go (about) 1 // Copyright (c) 2019 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package vpp2101 16 17 import ( 18 "fmt" 19 "net" 20 "sort" 21 "strings" 22 23 "google.golang.org/protobuf/proto" 24 25 vpp_nat "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/nat44" 26 "go.ligato.io/vpp-agent/v3/plugins/vpp/binapi/vpp2101/nat_types" 27 "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx" 28 ifs "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 29 nat "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/nat" 30 ) 31 32 // DNATs sorted by tags 33 type dnatMap map[string]*nat.DNat44 34 35 // static mappings sorted by tags 36 type stMappingMap map[string][]*nat.DNat44_StaticMapping 37 38 // identity mappings sorted by tags 39 type idMappingMap map[string][]*nat.DNat44_IdentityMapping 40 41 // WithLegacyStartupConf returns true if the loaded VPP NAT plugin is still using 42 // the legacy startup NAT configuration (this is the case for VPP <= 20.09). 43 func (h *NatVppHandler) WithLegacyStartupConf() bool { 44 return false 45 } 46 47 func (h *NatVppHandler) DefaultNat44GlobalConfig() *nat.Nat44Global { 48 return &nat.Nat44Global{ 49 Forwarding: false, 50 EndpointIndependent: true, 51 NatInterfaces: nil, 52 AddressPool: nil, 53 VirtualReassembly: nil, // VirtualReassembly is not part of NAT API in VPP 20.01+ anymore 54 } 55 } 56 57 // Nat44GlobalConfigDump dumps global NAT44 config in NB format. 58 func (h *NatVppHandler) Nat44GlobalConfigDump(dumpDeprecated bool) (cfg *nat.Nat44Global, err error) { 59 cfg = &nat.Nat44Global{} 60 req := &vpp_nat.Nat44ShowRunningConfig{} 61 reply := &vpp_nat.Nat44ShowRunningConfigReply{} 62 if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil { 63 return nil, err 64 } 65 cfg.EndpointIndependent = reply.Flags&vpp_nat.NAT44_IS_ENDPOINT_DEPENDENT == 0 66 cfg.Forwarding = reply.ForwardingEnabled 67 cfg.VirtualReassembly, _, err = h.virtualReassemblyDump() 68 if err != nil { 69 return nil, err 70 } 71 if dumpDeprecated { 72 cfg.NatInterfaces, err = h.nat44InterfaceDump() 73 if err != nil { 74 return nil, err 75 } 76 cfg.AddressPool, err = h.nat44AddressDump() 77 if err != nil { 78 return nil, err 79 } 80 } 81 return 82 } 83 84 // DNat44Dump dumps all configured DNAT-44 configurations ordered by label. 85 func (h *NatVppHandler) DNat44Dump() (dnats []*nat.DNat44, err error) { 86 dnatMap := make(dnatMap) 87 88 // Static mappings 89 natStMappings, err := h.nat44StaticMappingDump() 90 if err != nil { 91 return nil, fmt.Errorf("failed to dump NAT44 static mappings: %v", err) 92 } 93 for label, mappings := range natStMappings { 94 dnat := getOrCreateDNAT(dnatMap, label) 95 dnat.StMappings = append(dnat.StMappings, mappings...) 96 } 97 98 // Static mappings with load balancer 99 natStLbMappings, err := h.nat44StaticMappingLbDump() 100 if err != nil { 101 return nil, fmt.Errorf("failed to dump NAT44 static mappings with load balancer: %v", err) 102 } 103 for label, mappings := range natStLbMappings { 104 dnat := getOrCreateDNAT(dnatMap, label) 105 dnat.StMappings = append(dnat.StMappings, mappings...) 106 } 107 108 // Identity mappings 109 natIDMappings, err := h.nat44IdentityMappingDump() 110 if err != nil { 111 return nil, fmt.Errorf("failed to dump NAT44 identity mappings: %v", err) 112 } 113 for label, mappings := range natIDMappings { 114 dnat := getOrCreateDNAT(dnatMap, label) 115 dnat.IdMappings = append(dnat.IdMappings, mappings...) 116 } 117 118 // Convert map of DNAT configurations into a list. 119 for _, dnat := range dnatMap { 120 dnats = append(dnats, dnat) 121 } 122 123 // sort to simplify testing 124 sort.Slice(dnats, func(i, j int) bool { return dnats[i].Label < dnats[j].Label }) 125 126 return dnats, nil 127 } 128 129 // Nat44InterfacesDump dumps NAT44 config of all NAT44-enabled interfaces. 130 func (h *NatVppHandler) Nat44InterfacesDump() (natIfs []*nat.Nat44Interface, err error) { 131 132 // dump NAT interfaces without output feature enabled 133 req1 := &vpp_nat.Nat44InterfaceDump{} 134 reqContext := h.callsChannel.SendMultiRequest(req1) 135 for { 136 msg := &vpp_nat.Nat44InterfaceDetails{} 137 stop, err := reqContext.ReceiveReply(msg) 138 if err != nil { 139 return nil, fmt.Errorf("failed to dump NAT44 interface: %v", err) 140 } 141 if stop { 142 break 143 } 144 ifName, _, found := h.ifIndexes.LookupBySwIfIndex(uint32(msg.SwIfIndex)) 145 if !found { 146 h.log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) 147 continue 148 } 149 flags := getNat44Flags(msg.Flags) 150 natIf := &nat.Nat44Interface{ 151 Name: ifName, 152 NatInside: flags.isInside, 153 NatOutside: flags.isOutside, 154 OutputFeature: false, 155 } 156 natIfs = append(natIfs, natIf) 157 } 158 159 // dump interfaces with output feature enabled 160 req2 := &vpp_nat.Nat44InterfaceOutputFeatureDump{} 161 reqContext = h.callsChannel.SendMultiRequest(req2) 162 for { 163 msg := &vpp_nat.Nat44InterfaceOutputFeatureDetails{} 164 stop, err := reqContext.ReceiveReply(msg) 165 if err != nil { 166 return nil, fmt.Errorf("failed to dump NAT44 interface output feature: %v", err) 167 } 168 if stop { 169 break 170 } 171 ifName, _, found := h.ifIndexes.LookupBySwIfIndex(uint32(msg.SwIfIndex)) 172 if !found { 173 h.log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) 174 continue 175 } 176 flags := getNat44Flags(msg.Flags) 177 natIf := &nat.Nat44Interface{ 178 Name: ifName, 179 NatInside: flags.isInside, 180 NatOutside: flags.isOutside, 181 OutputFeature: true, 182 } 183 if !natIf.NatInside && !natIf.NatOutside { 184 natIf.NatOutside = true 185 } 186 natIfs = append(natIfs, natIf) 187 } 188 return 189 } 190 191 // Nat44AddressPoolsDump dumps all configured NAT44 address pools. 192 func (h *NatVppHandler) Nat44AddressPoolsDump() (natPools []*nat.Nat44AddressPool, err error) { 193 var curPool *nat.Nat44AddressPool 194 var lastIP net.IP 195 196 req := &vpp_nat.Nat44AddressDump{} 197 reqContext := h.callsChannel.SendMultiRequest(req) 198 199 for { 200 msg := &vpp_nat.Nat44AddressDetails{} 201 stop, err := reqContext.ReceiveReply(msg) 202 if err != nil { 203 return nil, fmt.Errorf("failed to dump NAT44 Address pool: %v", err) 204 } 205 if stop { 206 break 207 } 208 ip := net.IP(msg.IPAddress[:]) 209 isTwiceNat := getNat44Flags(msg.Flags).isTwiceNat 210 // merge subsequent IPs into a single pool 211 if curPool != nil && curPool.VrfId == msg.VrfID && curPool.TwiceNat == isTwiceNat && ip.Equal(incIP(lastIP)) { 212 // update current pool 213 curPool.LastIp = ip.String() 214 } else { 215 // start a new pool 216 pool := &nat.Nat44AddressPool{ 217 FirstIp: ip.String(), 218 VrfId: msg.VrfID, 219 TwiceNat: isTwiceNat, 220 } 221 curPool = pool 222 natPools = append(natPools, pool) 223 } 224 lastIP = ip 225 } 226 return 227 } 228 229 // nat44AddressDump returns NAT44 address pool configured in the VPP. 230 // Deprecated. Functionality moved to Nat44AddressPoolsDump. Kept for backward compatibility. 231 func (h *NatVppHandler) nat44AddressDump() (addressPool []*nat.Nat44Global_Address, err error) { 232 req := &vpp_nat.Nat44AddressDump{} 233 reqContext := h.callsChannel.SendMultiRequest(req) 234 235 for { 236 msg := &vpp_nat.Nat44AddressDetails{} 237 stop, err := reqContext.ReceiveReply(msg) 238 if err != nil { 239 return nil, fmt.Errorf("failed to dump NAT44 Address pool: %v", err) 240 } 241 if stop { 242 break 243 } 244 245 addressPool = append(addressPool, &nat.Nat44Global_Address{ 246 Address: net.IP(msg.IPAddress[:]).String(), 247 VrfId: msg.VrfID, 248 TwiceNat: getNat44Flags(msg.Flags).isTwiceNat, 249 }) 250 } 251 252 return 253 } 254 255 // virtualReassemblyDump returns current NAT virtual-reassembly configuration. 256 func (h *NatVppHandler) virtualReassemblyDump() (vrIPv4 *nat.VirtualReassembly, vrIPv6 *nat.VirtualReassembly, err error) { 257 /*ipv4vr, err := h.ip.IPReassemblyGet(context.TODO(), &vpp_ip.IPReassemblyGet{IsIP6: false}) 258 if err != nil { 259 return nil, nil, fmt.Errorf("getting virtual reassembly IPv4 config failed: %w", err) 260 } 261 h.log.Debugf("IP Reassembly config IPv4: %+v\n", ipv4vr) 262 ipv6vr, err := h.ip.IPReassemblyGet(context.TODO(), &vpp_ip.IPReassemblyGet{IsIP6: true}) 263 if err != nil { 264 return nil, nil, fmt.Errorf("getting virtual reassembly IPv6 config failed: %w", err) 265 } 266 h.log.Debugf("IP Reassembly config IPv6: %+v\n", ipv6vr)*/ 267 268 // Virtual Reassembly has been removed from NAT API in VPP (moved to IP API) 269 // TODO: define IPReassembly model in L3 plugin 270 return nil, nil, nil 271 /*vrIPv4 = &nat.VirtualReassembly{ 272 Timeout: reply.IP4Timeout, 273 MaxReassemblies: uint32(reply.IP4MaxReass), 274 MaxFragments: uint32(reply.IP4MaxFrag), 275 DropFragments: uintToBool(reply.IP4DropFrag), 276 } 277 vrIPv6 = &nat.VirtualReassembly{ 278 Timeout: reply.IP6Timeout, 279 MaxReassemblies: uint32(reply.IP6MaxReass), 280 MaxFragments: uint32(reply.IP6MaxFrag), 281 DropFragments: uintToBool(reply.IP6DropFrag), 282 } 283 return*/ 284 } 285 286 // nat44StaticMappingDump returns a map of NAT44 static mappings sorted by tags 287 func (h *NatVppHandler) nat44StaticMappingDump() (entries stMappingMap, err error) { 288 entries = make(stMappingMap) 289 childMappings := make(stMappingMap) 290 req := &vpp_nat.Nat44StaticMappingDump{} 291 reqContext := h.callsChannel.SendMultiRequest(req) 292 293 for { 294 msg := &vpp_nat.Nat44StaticMappingDetails{} 295 stop, err := reqContext.ReceiveReply(msg) 296 if err != nil { 297 return nil, fmt.Errorf("failed to dump NAT44 static mapping: %v", err) 298 } 299 if stop { 300 break 301 } 302 lcIPAddress := net.IP(msg.LocalIPAddress[:]).String() 303 exIPAddress := net.IP(msg.ExternalIPAddress[:]).String() 304 305 // Parse tag (DNAT label) 306 tag := strings.TrimRight(msg.Tag, "\x00") 307 if _, hasTag := entries[tag]; !hasTag { 308 entries[tag] = []*nat.DNat44_StaticMapping{} 309 childMappings[tag] = []*nat.DNat44_StaticMapping{} 310 } 311 312 // resolve interface name 313 var ( 314 found bool 315 extIfaceName string 316 extIfaceMeta *ifaceidx.IfaceMetadata 317 ) 318 if msg.ExternalSwIfIndex != NoInterface { 319 extIfaceName, extIfaceMeta, found = h.ifIndexes.LookupBySwIfIndex(uint32(msg.ExternalSwIfIndex)) 320 if !found { 321 h.log.Warnf("Interface with index %v not found in the mapping", msg.ExternalSwIfIndex) 322 continue 323 } 324 } 325 326 flags := getNat44Flags(msg.Flags) 327 328 // Add mapping into the map. 329 mapping := &nat.DNat44_StaticMapping{ 330 ExternalInterface: extIfaceName, 331 ExternalIp: exIPAddress, 332 ExternalPort: uint32(msg.ExternalPort), 333 LocalIps: []*nat.DNat44_StaticMapping_LocalIP{ // single-value 334 { 335 VrfId: msg.VrfID, 336 LocalIp: lcIPAddress, 337 LocalPort: uint32(msg.LocalPort), 338 }, 339 }, 340 Protocol: h.protocolNumberToNBValue(msg.Protocol), 341 TwiceNat: h.getTwiceNatMode(flags.isTwiceNat, flags.isSelfTwiceNat), 342 // if there is only one backend the affinity can not be set 343 SessionAffinity: 0, 344 } 345 entries[tag] = append(entries[tag], mapping) 346 347 if msg.ExternalSwIfIndex != NoInterface { 348 // collect auto-generated "child" mappings (interface replaced with every assigned IP address) 349 for _, ipAddr := range h.getInterfaceIPAddresses(extIfaceName, extIfaceMeta) { 350 childMapping := proto.Clone(mapping).(*nat.DNat44_StaticMapping) 351 childMapping.ExternalIp = ipAddr 352 childMapping.ExternalInterface = "" 353 childMappings[tag] = append(childMappings[tag], childMapping) 354 } 355 } 356 } 357 358 // do not dump auto-generated child mappings 359 for tag, mappings := range entries { 360 var filtered []*nat.DNat44_StaticMapping 361 for _, mapping := range mappings { 362 isChild := false 363 for _, child := range childMappings[tag] { 364 if proto.Equal(mapping, child) { 365 isChild = true 366 break 367 } 368 } 369 if !isChild { 370 filtered = append(filtered, mapping) 371 } 372 } 373 entries[tag] = filtered 374 } 375 return entries, nil 376 } 377 378 // nat44StaticMappingLbDump returns a map of NAT44 static mapping with load balancing sorted by tags. 379 func (h *NatVppHandler) nat44StaticMappingLbDump() (entries stMappingMap, err error) { 380 entries = make(stMappingMap) 381 req := &vpp_nat.Nat44LbStaticMappingDump{} 382 reqContext := h.callsChannel.SendMultiRequest(req) 383 384 for { 385 msg := &vpp_nat.Nat44LbStaticMappingDetails{} 386 stop, err := reqContext.ReceiveReply(msg) 387 if err != nil { 388 return nil, fmt.Errorf("failed to dump NAT44 lb-static mapping: %v", err) 389 } 390 if stop { 391 break 392 } 393 394 // Parse tag (DNAT label) 395 tag := strings.TrimRight(msg.Tag, "\x00") 396 if _, hasTag := entries[tag]; !hasTag { 397 entries[tag] = []*nat.DNat44_StaticMapping{} 398 } 399 400 // Prepare localIPs 401 var locals []*nat.DNat44_StaticMapping_LocalIP 402 for _, localIPVal := range msg.Locals { 403 locals = append(locals, &nat.DNat44_StaticMapping_LocalIP{ 404 VrfId: localIPVal.VrfID, 405 LocalIp: net.IP(localIPVal.Addr[:]).String(), 406 LocalPort: uint32(localIPVal.Port), 407 Probability: uint32(localIPVal.Probability), 408 }) 409 } 410 exIPAddress := net.IP(msg.ExternalAddr[:]).String() 411 412 flags := getNat44Flags(msg.Flags) 413 414 // Add mapping into the map. 415 mapping := &nat.DNat44_StaticMapping{ 416 ExternalIp: exIPAddress, 417 ExternalPort: uint32(msg.ExternalPort), 418 LocalIps: locals, 419 Protocol: h.protocolNumberToNBValue(msg.Protocol), 420 TwiceNat: h.getTwiceNatMode(flags.isTwiceNat, flags.isSelfTwiceNat), 421 SessionAffinity: msg.Affinity, 422 } 423 entries[tag] = append(entries[tag], mapping) 424 } 425 426 return entries, nil 427 } 428 429 // nat44IdentityMappingDump returns a map of NAT44 identity mappings sorted by tags. 430 func (h *NatVppHandler) nat44IdentityMappingDump() (entries idMappingMap, err error) { 431 entries = make(idMappingMap) 432 childMappings := make(idMappingMap) 433 req := &vpp_nat.Nat44IdentityMappingDump{} 434 reqContext := h.callsChannel.SendMultiRequest(req) 435 436 for { 437 msg := &vpp_nat.Nat44IdentityMappingDetails{} 438 stop, err := reqContext.ReceiveReply(msg) 439 if err != nil { 440 return nil, fmt.Errorf("failed to dump NAT44 identity mapping: %v", err) 441 } 442 if stop { 443 break 444 } 445 446 // Parse tag (DNAT label) 447 tag := strings.TrimRight(msg.Tag, "\x00") 448 if _, hasTag := entries[tag]; !hasTag { 449 entries[tag] = []*nat.DNat44_IdentityMapping{} 450 childMappings[tag] = []*nat.DNat44_IdentityMapping{} 451 } 452 453 // resolve interface name 454 var ( 455 found bool 456 ifaceName string 457 ifaceMeta *ifaceidx.IfaceMetadata 458 ) 459 if msg.SwIfIndex != NoInterface { 460 ifaceName, ifaceMeta, found = h.ifIndexes.LookupBySwIfIndex(uint32(msg.SwIfIndex)) 461 if !found { 462 h.log.Warnf("Interface with index %v not found in the mapping", msg.SwIfIndex) 463 continue 464 } 465 } 466 467 // Add mapping into the map. 468 mapping := &nat.DNat44_IdentityMapping{ 469 IpAddress: net.IP(msg.IPAddress[:]).String(), 470 VrfId: msg.VrfID, 471 Interface: ifaceName, 472 Port: uint32(msg.Port), 473 Protocol: h.protocolNumberToNBValue(msg.Protocol), 474 } 475 entries[tag] = append(entries[tag], mapping) 476 477 if msg.SwIfIndex != NoInterface { 478 // collect auto-generated "child" mappings (interface replaced with every assigned IP address) 479 for _, ipAddr := range h.getInterfaceIPAddresses(ifaceName, ifaceMeta) { 480 childMapping := proto.Clone(mapping).(*nat.DNat44_IdentityMapping) 481 childMapping.IpAddress = ipAddr 482 childMapping.Interface = "" 483 childMappings[tag] = append(childMappings[tag], childMapping) 484 } 485 } 486 } 487 488 // do not dump auto-generated child mappings 489 for tag, mappings := range entries { 490 var filtered []*nat.DNat44_IdentityMapping 491 for _, mapping := range mappings { 492 isChild := false 493 for _, child := range childMappings[tag] { 494 if proto.Equal(mapping, child) { 495 isChild = true 496 break 497 } 498 } 499 if !isChild { 500 filtered = append(filtered, mapping) 501 } 502 } 503 entries[tag] = filtered 504 } 505 506 return entries, nil 507 } 508 509 // nat44InterfaceDump dumps NAT44 interface features. 510 // Deprecated. Functionality moved to Nat44Nat44InterfacesDump. Kept for backward compatibility. 511 func (h *NatVppHandler) nat44InterfaceDump() (interfaces []*nat.Nat44Global_Interface, err error) { 512 513 /* dump non-Output interfaces first */ 514 req1 := &vpp_nat.Nat44InterfaceDump{} 515 reqContext := h.callsChannel.SendMultiRequest(req1) 516 517 for { 518 msg := &vpp_nat.Nat44InterfaceDetails{} 519 stop, err := reqContext.ReceiveReply(msg) 520 if err != nil { 521 return nil, fmt.Errorf("failed to dump NAT44 interface: %v", err) 522 } 523 if stop { 524 break 525 } 526 527 // Find interface name 528 ifName, _, found := h.ifIndexes.LookupBySwIfIndex(uint32(msg.SwIfIndex)) 529 if !found { 530 h.log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) 531 continue 532 } 533 534 flags := getNat44Flags(msg.Flags) 535 536 if flags.isInside { 537 interfaces = append(interfaces, &nat.Nat44Global_Interface{ 538 Name: ifName, 539 IsInside: true, 540 }) 541 } else { 542 interfaces = append(interfaces, &nat.Nat44Global_Interface{ 543 Name: ifName, 544 IsInside: false, 545 }) 546 } 547 } 548 549 /* dump Output interfaces next */ 550 req2 := &vpp_nat.Nat44InterfaceOutputFeatureDump{} 551 reqContext = h.callsChannel.SendMultiRequest(req2) 552 553 for { 554 msg := &vpp_nat.Nat44InterfaceOutputFeatureDetails{} 555 stop, err := reqContext.ReceiveReply(msg) 556 if err != nil { 557 return nil, fmt.Errorf("failed to dump NAT44 interface output feature: %v", err) 558 } 559 if stop { 560 break 561 } 562 563 // Find interface name 564 ifName, _, found := h.ifIndexes.LookupBySwIfIndex(uint32(msg.SwIfIndex)) 565 if !found { 566 h.log.Warnf("Interface with index %d not found in the mapping", msg.SwIfIndex) 567 continue 568 } 569 570 flags := getNat44Flags(msg.Flags) 571 572 interfaces = append(interfaces, &nat.Nat44Global_Interface{ 573 Name: ifName, 574 IsInside: flags.isInside, 575 OutputFeature: true, 576 }) 577 } 578 579 return interfaces, nil 580 } 581 582 func (h *NatVppHandler) getInterfaceIPAddresses(ifaceName string, ifaceMeta *ifaceidx.IfaceMetadata) (ipAddrs []string) { 583 ipAddrNets := ifaceMeta.IPAddresses 584 dhcpLease, hasDHCPLease := h.dhcpIndex.GetValue(ifaceName) 585 if hasDHCPLease { 586 lease := dhcpLease.(*ifs.DHCPLease) 587 ipAddrNets = append(ipAddrNets, lease.HostIpAddress) 588 } 589 for _, ipAddrNet := range ipAddrNets { 590 ipAddr := strings.Split(ipAddrNet, "/")[0] 591 ipAddrs = append(ipAddrs, ipAddr) 592 } 593 return ipAddrs 594 } 595 596 // protocolNumberToNBValue converts protocol numeric representation into the corresponding enum 597 // enum value from the NB model. 598 func (h *NatVppHandler) protocolNumberToNBValue(protocol uint8) (proto nat.DNat44_Protocol) { 599 switch protocol { 600 case TCP: 601 return nat.DNat44_TCP 602 case UDP: 603 return nat.DNat44_UDP 604 case ICMP: 605 return nat.DNat44_ICMP 606 default: 607 h.log.Warnf("Unknown protocol %v", protocol) 608 return 0 609 } 610 } 611 612 // protocolNBValueToNumber converts protocol enum value from the NB model into the 613 // corresponding numeric representation. 614 func (h *NatVppHandler) protocolNBValueToNumber(protocol nat.DNat44_Protocol) (proto uint8) { 615 switch protocol { 616 case nat.DNat44_TCP: 617 return TCP 618 case nat.DNat44_UDP: 619 return UDP 620 case nat.DNat44_ICMP: 621 return ICMP 622 default: 623 h.log.Warnf("Unknown protocol %v, defaulting to TCP", protocol) 624 return TCP 625 } 626 } 627 628 func (h *NatVppHandler) getTwiceNatMode(twiceNat, selfTwiceNat bool) nat.DNat44_StaticMapping_TwiceNatMode { 629 if twiceNat { 630 if selfTwiceNat { 631 h.log.Warnf("Both TwiceNAT and self-TwiceNAT are enabled") 632 return 0 633 } 634 return nat.DNat44_StaticMapping_ENABLED 635 } 636 if selfTwiceNat { 637 return nat.DNat44_StaticMapping_SELF 638 } 639 return nat.DNat44_StaticMapping_DISABLED 640 } 641 642 func getOrCreateDNAT(dnats dnatMap, label string) *nat.DNat44 { 643 if _, created := dnats[label]; !created { 644 dnats[label] = &nat.DNat44{Label: label} 645 } 646 return dnats[label] 647 } 648 649 func getNat44Flags(flags nat_types.NatConfigFlags) *nat44Flags { 650 natFlags := &nat44Flags{} 651 if flags&nat_types.NAT_IS_EXT_HOST_VALID != 0 { 652 natFlags.isExtHostValid = true 653 } 654 if flags&nat_types.NAT_IS_STATIC != 0 { 655 natFlags.isStatic = true 656 } 657 if flags&nat_types.NAT_IS_INSIDE != 0 { 658 natFlags.isInside = true 659 } 660 if flags&nat_types.NAT_IS_OUTSIDE != 0 { 661 natFlags.isOutside = true 662 } 663 if flags&nat_types.NAT_IS_ADDR_ONLY != 0 { 664 natFlags.isAddrOnly = true 665 } 666 if flags&nat_types.NAT_IS_OUT2IN_ONLY != 0 { 667 natFlags.isOut2In = true 668 } 669 if flags&nat_types.NAT_IS_SELF_TWICE_NAT != 0 { 670 natFlags.isSelfTwiceNat = true 671 } 672 if flags&nat_types.NAT_IS_TWICE_NAT != 0 { 673 natFlags.isTwiceNat = true 674 } 675 return natFlags 676 } 677 678 // incIP increments IP address and returns it. 679 // Based on: https://play.golang.org/p/m8TNTtygK0 680 func incIP(ip net.IP) net.IP { 681 retIP := make(net.IP, len(ip)) 682 copy(retIP, ip) 683 for j := len(retIP) - 1; j >= 0; j-- { 684 retIP[j]++ 685 if retIP[j] > 0 { 686 break 687 } 688 } 689 return retIP 690 }