+
+ /**
+ * router association to vpn
+ *
+ */
+ public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
+ LOG.debug("NAT Service : Router associated to BGP VPN");
+ if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
+ long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
+
+ LOG.debug("BGP VPN ID value {} ", bgpVpnId);
+
+ if(bgpVpnId != NatConstants.INVALID_ID){
+ LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
+ RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
+
+ // Get the allocated Primary NAPT Switch for this router
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("Router ID value {} ", routerId);
+ BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+
+ LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
+ addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
+
+ // Get the group ID
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, bgpVpnId, routerId);
+ }
+ }
+ }
+
+ /**
+ * router disassociation from vpn
+ *
+ */
+ public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
+ LOG.debug("NAT Service : Router dissociated from BGP VPN");
+ if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
+ long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
+ LOG.debug("BGP VPN ID value {} ", bgpVpnId);
+
+ // Get the allocated Primary NAPT Switch for this router
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("Router ID value {} ", routerId);
+ BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+
+ LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
+ addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
+
+ // Get the group ID
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, NatConstants.INVALID_ID, routerId);
+ }
+ }
+
+ boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
+ InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
+ (Routers.class, new RoutersKey(routerUuid.getValue())).build();
+ Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
+ if (routerData.isPresent() && routerData.get().isEnableSnat()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long groupId, long bgpVpnId, long routerId){
+ long changedVpnId = bgpVpnId;
+ String logMsg = "NAT Service : Update the BGP VPN ID {}";
+ if (bgpVpnId == NatConstants.INVALID_ID){
+ changedVpnId = routerId;
+ logMsg = "NAT Service : Update the router ID {}";
+ }
+
+ LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
+ changedVpnId, groupId, primarySwitchId);
+ FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(primarySwitchId, routerName, groupId, changedVpnId);
+ mdsalManager.installFlow(flowEntity);
+
+ LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
+ " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
+ installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
+
+ LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
+ " controller in the Primary switch {}", changedVpnId, primarySwitchId);
+ createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
+
+ LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
+ changedVpnId, primarySwitchId);
+ installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
+
+ LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
+ " in the Primary switch {}", changedVpnId, primarySwitchId);
+ updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
+
+ List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ for(BigInteger dpnId : switches) {
+ // Update the BGP VPN ID in the SNAT miss entry to group
+ if( !dpnId.equals(primarySwitchId) ) {
+ LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
+ changedVpnId, groupId, dpnId);
+ flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
+ mdsalManager.installFlow(flowEntity);
+ }
+ }
+ }
+
+ public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
+ //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
+ if(ipPortMapping == null){
+ LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
+ return;
+ }
+
+ List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
+ for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+ for(IpPortMap ipPortMap : ipPortMaps){
+ String ipPortInternal = ipPortMap.getIpPortInternal();
+ String[] ipPortParts = ipPortInternal.split(":");
+ if(ipPortParts.length != 2) {
+ LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
+ return;
+ }
+ String internalIp = ipPortParts[0];
+ String internalPort = ipPortParts[1];
+
+ ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
+ NAPTEntryEvent.Protocol protocol;
+ switch (protocolTypes){
+ case TCP:
+ protocol = NAPTEntryEvent.Protocol.TCP;
+ break;
+ case UDP:
+ protocol = NAPTEntryEvent.Protocol.UDP;
+ break;
+ default:
+ protocol = NAPTEntryEvent.Protocol.TCP;
+ }
+ SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
+ SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
+ long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
+ naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
+ internalAddress, externalAddress, protocol);
+ naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
+ externalAddress, internalAddress, protocol);
+
+ }
+ }
+ }
+
+ public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
+
+ LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ List<ActionInfo> actionsInfo = new ArrayList<>();
+
+ ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(changedVpnId)}) ;
+ actionsInfo.add(actionSetField);
+ LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
+ actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+ String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
+
+ LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
+ return flowEntity;
+ }
+
+ // TODO : Replace this with ITM Rpc once its available with full functionality
+ protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
+ LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
+ FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
+ mdsalManager.installFlow(flowEntity);
+
+ }
+
+ private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
+ LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
+ BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
+ BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
+ { bgpVpnIdAsBigInt, MetaDataUtil.METADATA_MASK_VRFID }));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
+ { NatConstants.OUTBOUND_NAPT_TABLE }));
+ String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
+ NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_TS_TABLE, matches, instructions);
+ return flowEntity;
+ }
+
+ public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
+ LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
+ FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
+ LOG.debug("NAT Service : Installing flow {}", flowEntity);
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
+ LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[]{0x0800L}));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
+ BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
+
+ String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
+ BigInteger cookie = getCookieOutboundFlow(routerId);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
+ 5, flowRef, 0, 0,
+ cookie, matches, instructions);
+ LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
+ return flowEntity;
+ }
+
+ public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
+ LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
+ FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
+ mdsalManager.installFlow(naptPfibFlowEntity);
+ }
+
+ public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
+
+ LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
+ ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
+ listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
+ instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
+
+ String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
+
+ LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
+ return flowEntity;
+ }
+