+
+ Action decTtl = decNwTtlAction();
+ l3ApplyActions.add(decTtl);
+
+ order += 1;
+ applyActions.add(setdEPG);
+ applyActions.add(setdCG);
+ applyActions.add(setNextHop);
+
+ applyActions.addAll(l3ApplyActions);
+ Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+ .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+ .build();
+
+ l3instructions.add(applyActionsIns);
+ Instruction gotoTable = new InstructionBuilder().setOrder(order++)
+ .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
+ .build();
+ l3instructions.add(gotoTable);
+ Layer3Match m = null;
+ Long etherType = null;
+ String ikey = null;
+ if (destL3Address.getIpAddress().getIpv4Address() != null) {
+ ikey = destL3Address.getIpAddress().getIpv4Address().getValue() + "/32";
+ etherType = IPv4;
+ m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
+ } else if (destL3Address.getIpAddress().getIpv6Address() != null) {
+ ikey = destL3Address.getIpAddress().getIpv6Address().getValue() + "/128";
+ etherType = IPv6;
+ m = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
+ } else {
+ LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", destL3Address.toString());
+ return null;
+ }
+
+ MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, matcherMac, etherType))
+ .setLayer3Match(m);
+ addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(epFwdCtxOrds.getL3Id())));
+ Match match = mb.build();
+ FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "localL3", match);
+ FlowBuilder flowb = base().setId(flowid)
+ .setPriority(Integer.valueOf(132))
+ .setMatch(match)
+ .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
+ return flowb.build();
+ }
+
+ private Flow createExternalL3RoutedFlow(Endpoint destEp, L3Address destL3Address, EndpointFwdCtxOrdinals epFwdCtxOrds,
+ Subnet srcSubnet, NodeId nodeId) {
+
+ Subnet destSubnet = null;
+ HashSet<Subnet> subnets = getSubnets(destEp.getTenant());
+ if (subnets == null) {
+ LOG.trace("No subnets in tenant {}", destEp.getTenant());
+ return null;
+ }
+ NetworkDomainId epNetworkContainment = getEPNetworkContainment(destEp);
+ for (Subnet subnet : subnets) {
+ // TODO Li alagalah add IPv6 support
+ if (subnet.getId().getValue().equals(epNetworkContainment.getValue())) {
+ destSubnet = subnet;
+ break;
+ }
+ }
+ if (destSubnet == null) {
+ LOG.trace("Destination IP address does not match any subnet in tenant {}", destL3Address.getIpAddress());
+ return null;
+ }
+
+ if (destSubnet.getVirtualRouterIp() == null) {
+ LOG.trace("Destination subnet {} for Endpoint {}.{} has no gateway IP", destSubnet.getIpPrefix(),
+ destL3Address.getKey());
+ return null;
+ }
+
+ if (srcSubnet.getVirtualRouterIp() == null) {
+ LOG.trace("Local subnet {} has no gateway IP", srcSubnet.getIpPrefix());
+ return null;
+ }
+ L3Context destL3c = getL3ContextForSubnet(destEp.getTenant(), destSubnet);
+ if (destL3c == null || destL3c.getId() == null) {
+ LOG.error("No L3 Context found associated with subnet {}", destSubnet.getId());
+ return null;
+ }
+ L3Context srcL3c = getL3ContextForSubnet(destEp.getTenant(), srcSubnet);
+ if (srcL3c == null || srcL3c.getId() == null) {
+ LOG.error("No L3 Context found associated with subnet {}", srcSubnet.getId());
+ return null;
+ }
+
+ if (!(srcL3c.getId().getValue().equals(destL3c.getId().getValue()))) {
+ LOG.trace("Trying to route between two L3Contexts {} and {}. Not currently supported.", srcL3c.getId()
+ .getValue(), destL3c.getId().getValue());
+ return null;
+ }
+
+ Endpoint l2Gw = getL2EndpointOfSubnetGateway(destEp.getTenant(), srcSubnet);
+ if(l2Gw == null) {
+ LOG.warn("The endpoint representing external gateway of subnet {} not found", srcSubnet);
+ return null;
+ }
+ MacAddress matcherMac = destEp.getMacAddress();
+ MacAddress destSubnetGatewayMac = l2Gw.getMacAddress();
+
+ ArrayList<Instruction> l3instructions = new ArrayList<>();
+ List<Action> applyActions = new ArrayList<>();
+ List<Action> l3ApplyActions = new ArrayList<>();
+
+ int order = 0;
+
+ Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
+ Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
+ Action setNextHop;
+
+ Set<NodeConnectorId> extPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
+ if (extPorts == null || !extPorts.iterator().hasNext()) {
+ LOG.warn("No external interface on node: {}. External Gateway {} is not reachable!", nodeId, l2Gw.getKey());
+ return null;
+ }
+ // only one external port is supported for now
+ NodeConnectorId extPort = extPorts.iterator().next();
+
+ long portNum;
+ try {
+ portNum = getOfPortNum(extPort);
+ } catch (NumberFormatException ex) {
+ LOG.warn("Could not parse port number {}", extPort, ex);
+ return null;
+ }
+
+ setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));