Commit b568262e authored by Muhammad Umair Khan's avatar Muhammad Umair Khan
Browse files

Fix TC-Engine: SNAT masquerade

parent 9abbb2cf
Loading
Loading
Loading
Loading
+89 −0
Original line number Diff line number Diff line
@@ -59,10 +59,12 @@ const mePrefix string = meepPrefix + "ME-"
const ingressPrefix string = meepPrefix + "INGRESS-"
const egressPrefix string = meepPrefix + "EGRESS-"
const egressSnatPrefix string = meepPrefix + "E-SNAT-"
const ingressSnatPrefix string = meepPrefix + "I-SNAT-"
const meSvcChain string = mePrefix + "SERVICES"
const ingressSvcChain string = ingressPrefix + "SERVICES"
const egressSvcChain string = egressPrefix + "SERVICES"
const egressSnatChain string = egressSnatPrefix + "SERVICES"
const ingressSnatChain string = ingressSnatPrefix + "SERVICES"
const maxChainLen int = 25
const capLetters string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
const ipAddrNone string = "n/a"
@@ -409,6 +411,18 @@ func refreshLbRules() {
	}
	delete(chainMap, egressSnatChain)

	// MEEP-I-SNAT-SERVICES
	_, exists = chainMap[ingressSnatChain]
	if !exists {
		log.Debug("Creating MEEP chain MEEP-I-SNAT-SERVICES")
		err = ipTbl.NewChain("nat", ingressSnatChain)
		if err != nil {
			log.Error("Failed to create chain. Error: ", err)
			return
		}
	}
	delete(chainMap, ingressSnatChain)

	// Reapply top-level routing rules if not present
	err = ipTbl.AppendUnique("nat", "OUTPUT", "-j", meSvcChain)
	if err != nil {
@@ -430,6 +444,11 @@ func refreshLbRules() {
		log.Error("Failed to set rule [-A POSTROUTING -o eth0 -j "+egressSnatChain+"]. Error: ", err)
		return
	}
	err = ipTbl.AppendUnique("nat", "POSTROUTING", "-o", "eth0", "-j", ingressSnatChain)
	if err != nil {
		log.Error("Failed to set rule [-A POSTROUTING -o eth0 -j "+ingressSnatChain+"]. Error: ", err)
		return
	}

	// Apply pod-specific LB rules stored in DB
	flushRequired = false
@@ -449,6 +468,8 @@ func refreshLbRules() {
			parentChain = ingressSvcChain
		} else if strings.Contains(chain, egressSnatPrefix) {
			parentChain = egressSnatChain
		} else if strings.Contains(chain, ingressSnatPrefix) {
			parentChain = ingressSnatChain
		} else if strings.Contains(chain, egressPrefix) {
			parentChain = egressSvcChain
		} else {
@@ -562,6 +583,11 @@ func refreshLbRulesHandler(key string, fields map[string]string, userData interf
					if err != nil {
						return err
					}
				} else if fields[fieldSvcType] == typeIngressSvc {
					err = addIngressSnatRule(fields, chainMap)
					if err != nil {
						return err
					}
				}
				return nil
			}
@@ -600,6 +626,11 @@ func refreshLbRulesHandler(key string, fields map[string]string, userData interf
		if err != nil {
			return err
		}
	} else if fields[fieldSvcType] == typeIngressSvc {
		err = addIngressSnatRule(fields, chainMap)
		if err != nil {
			return err
		}
	}

	flushRequired = true
@@ -664,6 +695,64 @@ func addEgressSnatRule(fields map[string]string, chainMap *map[string]bool) erro
	return nil
}

func addIngressSnatRule(fields map[string]string, chainMap *map[string]bool) error {
	var err error
	servicePrefix := ingressSnatPrefix + svcPrefix
	service := servicePrefix + strings.ToUpper(fields[fieldSvcName]) + "-" + fields[fieldSvcPort]
	var args []string
	args = append(args, "-p", fields[fieldSvcProtocol], "-d", fields[fieldLbSvcIp], "--dport", fields[fieldLbSvcPort],
		"-j", "MASQUERADE", "-m", "comment", "--comment", service)

	// Retrieve service chain name if service exists
	serviceChain, exists := serviceChains[service]
	if exists {
		// Check if chain exists
		_, exists = (*chainMap)[serviceChain]
		if exists {
			// Check if rule requires update
			exists, err = ipTbl.Exists("nat", serviceChain, args...)
			if err != nil {
				log.Error("Failed to check if rule exists. Error: ", err)
				return err
			}

			// No update required. Remove chain from chain map and return.
			if exists {
				delete(*chainMap, serviceChain)
				return nil
			}
		}
	}

	// Create new service chain name
	log.Debug("Creating new service chain mapping for SNAT service: ", service)
	serviceChain = servicePrefix + randSeq(maxChainLen-len(servicePrefix))
	serviceChains[service] = serviceChain

	// Create MEEP service chain
	log.Debug("Creating MEEP chain ", serviceChain)
	err = ipTbl.NewChain("nat", serviceChain)
	if err != nil {
		log.Error("Failed to create chain. Error: ", err)
		return err
	}

	// Create service routing rules
	err = ipTbl.AppendUnique("nat", ingressSnatChain, "-j", serviceChain)
	if err != nil {
		log.Error("Failed to set rule [-A ", ingressSnatChain, " -j ", serviceChain, "]. Error: ", err)
		return err
	}
	err = ipTbl.AppendUnique("nat", serviceChain, args...)
	if err != nil {
		log.Error("Failed to set rule [-A ", ingressSnatChain, " -j ", serviceChain, " ", args, "]. Error: ", err)
		return err
	}

	flushRequired = true
	return nil
}

// refreshDests - Refresh destinations to match valid DB entries
func refreshDests() {
	// Get list of destinations with valid IP addresses