use of org.opendaylight.netvirt.natservice.internal.NaptPacketInHandler.NatPacketProcessingState in project netvirt by opendaylight.
the class NaptEventHandler method handleEvent.
// TODO Clean up the exception handling
@SuppressWarnings("checkstyle:IllegalCatch")
public void handleEvent(final NAPTEntryEvent naptEntryEvent) {
/*
Flow programming logic of the OUTBOUND NAPT TABLE :
1) Get the internal IP address, port number, router ID from the event.
2) Use the NAPT service getExternalAddressMapping() to get the External IP and the port.
3) Build the flow for replacing the Internal IP and port with the External IP and port.
a) Write the matching criteria.
b) Match the router ID in the metadata.
d) Write the VPN ID to the metadata.
e) Write the other data.
f) Set the apply actions instruction with the action setfield.
4) Write the flow to the OUTBOUND NAPT Table and forward to FIB table for routing the traffic.
Flow programming logic of the INBOUND NAPT TABLE :
Same as Outbound table logic except that :
1) Build the flow for replacing the External IP and port with the Internal IP and port.
2) Match the VPN ID in the metadata.
3) Write the router ID to the metadata.
5) Write the flow to the INBOUND NAPT Table and forward to FIB table for routing the traffic.
*/
try {
Long routerId = naptEntryEvent.getRouterId();
LOG.trace("handleEvent : Time Elapsed before procesing snat ({}:{}) packet is {} ms," + "routerId: {},isPktProcessed:{}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), System.currentTimeMillis() - naptEntryEvent.getObjectCreationTime(), routerId, naptEntryEvent.isPktProcessed());
// Get the DPN ID
BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
long bgpVpnId = NatConstants.INVALID_ID;
if (dpnId == null) {
LOG.warn("handleEvent : dpnId is null. Assuming the router ID {} as the BGP VPN ID and proceeding....", routerId);
bgpVpnId = routerId;
LOG.debug("handleEvent : BGP VPN ID {}", bgpVpnId);
String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
if (routerName == null) {
LOG.error("handleEvent : Unable to find router for VpnName {}", vpnName);
return;
}
routerId = NatUtil.getVpnId(dataBroker, routerName);
LOG.debug("handleEvent : Router ID {}", routerId);
dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
if (dpnId == null) {
LOG.error("handleEvent : dpnId is null for the router {}", routerId);
return;
}
}
if (naptEntryEvent.getOperation() == NAPTEntryEvent.Operation.ADD) {
LOG.debug("handleEvent : Inside Add operation of NaptEventHandler");
// Build and install the NAPT translation flows in the Outbound and Inbound NAPT tables
if (!naptEntryEvent.isPktProcessed()) {
// Get the External Gateway MAC Address
String extGwMacAddress = NatUtil.getExtGwMacAddFromRouterId(dataBroker, routerId);
if (extGwMacAddress != null) {
LOG.debug("handleEvent : External Gateway MAC address {} found for External Router ID {}", extGwMacAddress, routerId);
} else {
LOG.error("handleEvent : No External Gateway MAC address found for External Router ID {}", routerId);
return;
}
// Get the external network ID from the ExternalRouter model
Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
if (networkId == null) {
LOG.error("handleEvent : networkId is null");
return;
}
// Get the VPN ID from the ExternalNetworks model
Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
if (vpnUuid == null) {
LOG.error("handleEvent : vpnUuid is null");
return;
}
Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
// Get the internal IpAddress, internal port number from the event
String internalIpAddress = naptEntryEvent.getIpAddress();
int internalPort = naptEntryEvent.getPortNumber();
SessionAddress internalAddress = new SessionAddress(internalIpAddress, internalPort);
NAPTEntryEvent.Protocol protocol = naptEntryEvent.getProtocol();
// Get the external IP address for the corresponding internal IP address
SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, naptEntryEvent.getProtocol());
if (externalAddress == null) {
LOG.error("handleEvent : externalAddress is null");
return;
}
Long vpnIdFromExternalSubnet = getVpnIdFromExternalSubnet(routerId, externalAddress.getIpAddress());
if (vpnIdFromExternalSubnet != NatConstants.INVALID_ID) {
vpnId = vpnIdFromExternalSubnet;
}
// Added External Gateway MAC Address
Future<RpcResult<AddFlowOutput>> addFlowResult = buildAndInstallNatFlowsOptionalRpc(dpnId, NwConstants.INBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId, externalAddress, internalAddress, protocol, extGwMacAddress, true);
final BigInteger finalDpnId = dpnId;
final Long finalVpnId = vpnId;
final Long finalRouterId = routerId;
final long finalBgpVpnId = bgpVpnId;
Futures.addCallback(JdkFutureAdapters.listenInPoolThread(addFlowResult), new FutureCallback<RpcResult<AddFlowOutput>>() {
@Override
public void onSuccess(@Nullable RpcResult<AddFlowOutput> result) {
LOG.debug("handleEvent : Configured inbound rule for {} to {}", internalAddress, externalAddress);
Future<RpcResult<AddFlowOutput>> addFlowResult = buildAndInstallNatFlowsOptionalRpc(finalDpnId, NwConstants.OUTBOUND_NAPT_TABLE, finalVpnId, finalRouterId, finalBgpVpnId, internalAddress, externalAddress, protocol, extGwMacAddress, true);
Futures.addCallback(JdkFutureAdapters.listenInPoolThread(addFlowResult), new FutureCallback<RpcResult<AddFlowOutput>>() {
@Override
public void onSuccess(@Nullable RpcResult<AddFlowOutput> result) {
LOG.debug("handleEvent : Configured outbound rule, sending packet out" + "from {} to {}", internalAddress, externalAddress);
prepareAndSendPacketOut(naptEntryEvent, finalRouterId);
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
LOG.error("handleEvent : Error configuring outbound " + "SNAT flows using RPC for SNAT connection from {} to {}", internalAddress, externalAddress);
}
}, MoreExecutors.directExecutor());
}
@Override
public void onFailure(@Nonnull Throwable throwable) {
LOG.error("handleEvent : Error configuring inbound SNAT flows " + "using RPC for SNAT connection from {} to {}", internalAddress, externalAddress);
}
}, MoreExecutors.directExecutor());
NatPacketProcessingState state = naptEntryEvent.getState();
if (state != null) {
state.setFlowInstalledTime(System.currentTimeMillis());
}
} else {
prepareAndSendPacketOut(naptEntryEvent, routerId);
}
LOG.trace("handleEvent : Time elapsed after Processsing snat ({}:{}) packet: {}ms,isPktProcessed:{} ", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), System.currentTimeMillis() - naptEntryEvent.getObjectCreationTime(), naptEntryEvent.isPktProcessed());
} else {
LOG.debug("handleEvent : Inside delete Operation of NaptEventHandler");
removeNatFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, routerId, naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber());
LOG.info("handleEvent : exited for removeEvent for IP {}, port {}, routerID : {}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
}
} catch (Exception e) {
LOG.error("handleEvent :Exception in NaptEventHandler.handleEvent() payload {}", naptEntryEvent, e);
}
}
Aggregations