import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.stream.Collectors;
-
import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
import org.opendaylight.genius.mdsalutil.ActionInfo;
import org.opendaylight.genius.mdsalutil.BucketInfo;
import org.opendaylight.genius.mdsalutil.FlowEntity;
-import org.opendaylight.genius.mdsalutil.GroupEntity;
import org.opendaylight.genius.mdsalutil.InstructionInfo;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.MatchInfo;
import org.opendaylight.genius.mdsalutil.actions.ActionMoveSpaToTpa;
import org.opendaylight.genius.mdsalutil.actions.ActionNxLoadInPort;
import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
-import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
import org.opendaylight.genius.mdsalutil.actions.ActionSetArpOp;
import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldEthernetSource;
import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.genius.mdsalutil.matches.MatchArpOp;
import org.opendaylight.genius.mdsalutil.matches.MatchArpTpa;
import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetEgressActionsForTunnelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCase;
import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.Uint64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger LOG = LoggerFactory.getLogger(ArpResponderUtil.class);
- private static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
-
/**
* A Utility class.
*/
private ArpResponderUtil() {
}
- /**
- * Install Group flow on the DPN.
- *
- * @param mdSalManager
- * Reference of MDSAL API RPC that provides API for installing
- * group flow
- * @param dpnId
- * DPN on which group flow to be installed
- * @param groupdId
- * Uniquely identifiable Group Id for the group flow
- * @param groupName
- * Name of the group flow
- * @param buckets
- * List of the bucket actions for the group flow
- */
- public static void installGroup(IMdsalApiManager mdSalManager, BigInteger dpnId, long groupdId, String groupName,
- List<BucketInfo> buckets) {
- LOG.trace("Installing group flow on dpn {}", dpnId);
- GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupdId, groupName, GroupTypes.GroupAll, buckets);
- mdSalManager.syncInstallGroup(groupEntity);
- try {
- Thread.sleep(WAIT_TIME_FOR_SYNC_INSTALL);
- } catch (InterruptedException e1) {
- LOG.warn("Error while waiting for ARP Responder Group Entry to be installed on DPN {} ", dpnId);
- }
- }
-
/**
* Get Default ARP Responder Drop flow on the DPN.
*
* @param dpnId
* DPN on which group flow to be installed
*/
- public static FlowEntity getArpResponderTableMissFlow(BigInteger dpnId) {
+ public static FlowEntity getArpResponderTableMissFlow(Uint64 dpnId) {
return MDSALUtil.buildFlowEntity(dpnId, NwConstants.ARP_RESPONDER_TABLE,
String.valueOf(NwConstants.ARP_RESPONDER_TABLE), NwConstants.TABLE_MISS_PRIORITY,
ArpResponderConstant.DROP_FLOW_NAME.value(), 0, 0, NwConstants.COOKIE_ARP_RESPONDER,
* Get Bucket Actions for ARP Responder Group Flow.
*
* <p>
- * Install Default Groups, Group has 3 Buckets
+ * Install Default Groups, Group has 1 Bucket
* </p>
* <ul>
- * <li>Punt to controller</li>
- * <li>Resubmit to Table {@link NwConstants#LPORT_DISPATCHER_TABLE}, for
- * ELAN flooding
* <li>Resubmit to Table {@link NwConstants#ARP_RESPONDER_TABLE}, for ARP
* Auto response from DPN itself</li>
* </ul>
*
* @param resubmitTableId
* Resubmit Flow Table Id
- * @param resubmitTableId2
- * Resubmit Flow Table Id
* @return List of bucket actions
*/
- public static List<BucketInfo> getDefaultBucketInfos(short resubmitTableId, short resubmitTableId2) {
- return Arrays.asList(
- new BucketInfo(Collections.singletonList(new ActionPuntToController())),
- new BucketInfo(Collections.singletonList(new ActionNxResubmit(resubmitTableId))),
- new BucketInfo(Collections.singletonList(new ActionNxResubmit(resubmitTableId2))));
+ public static List<BucketInfo> getDefaultBucketInfos(short resubmitTableId) {
+ return Collections.singletonList(
+ new BucketInfo(Collections.singletonList(new ActionNxResubmit(resubmitTableId))));
}
/**
public static List<MatchInfo> getMatchCriteria(int lportTag, ElanInstance elanInstance,
String ipAddress) {
- BigInteger metadata = ElanHelper.getElanMetadataLabel(elanInstance.getElanTag(), lportTag);
- BigInteger metadataMask = ElanHelper.getElanMetadataMask();
+ Uint64 metadata = ElanHelper.getElanMetadataLabel(elanInstance.getElanTag().toJava(), lportTag);
+ Uint64 metadataMask = ElanHelper.getElanMetadataMask();
return Arrays.asList(MatchEthernetType.ARP, MatchArpOp.REQUEST, new MatchArpTpa(ipAddress, "32"),
new MatchMetadata(metadata, metadataMask));
* MacAddress for which ARP Response packet is to be generated
* @return List of ARP Responder Actions actions
*/
- public static List<Action> getActions(IInterfaceManager ifaceMgrRpcService, String ifName, String ipAddress,
- String macAddress) {
+ private static List<Action> getActions(IInterfaceManager ifaceMgrRpcService, ItmRpcService itmRpcService,
+ String ifName, String ipAddress, String macAddress,
+ boolean isTunnelInterface) {
AtomicInteger actionCounter = new AtomicInteger();
List<Action> actions = arpActions.apply(actionCounter, macAddress, ipAddress);
- actions.addAll(getEgressActionsForInterface(ifaceMgrRpcService, ifName, actionCounter.get()));
+ actions.addAll(getEgressActionsForInterface(ifaceMgrRpcService, itmRpcService, ifName, actionCounter.get(),
+ isTunnelInterface));
LOG.trace("Total Number of actions is {}", actionCounter);
return actions;
new ActionMoveSpaToTpa().buildAction(actionCounter.getAndIncrement()),
new ActionLoadMacToSha(new MacAddress(mac)).buildAction(actionCounter.getAndIncrement()),
new ActionLoadIpToSpa(ip).buildAction(actionCounter.getAndIncrement()),
- new ActionNxLoadInPort(BigInteger.ZERO).buildAction(actionCounter.getAndIncrement()));
+ new ActionNxLoadInPort(Uint64.valueOf(BigInteger.ZERO)).buildAction(actionCounter.getAndIncrement()));
return actions;
};
* Get instruction list for ARP responder flows.
*/
public static List<Instruction> getInterfaceInstructions(IInterfaceManager ifaceMgrRpcService, String interfaceName,
- String ipAddress, String macAddress) {
- List<Action> actions = ArpResponderUtil.getActions(ifaceMgrRpcService, interfaceName, ipAddress, macAddress);
+ String ipAddress, String macAddress, ItmRpcService itmRpcService) {
+ List<Action> actions = ArpResponderUtil.getActions(ifaceMgrRpcService, itmRpcService, interfaceName, ipAddress,
+ macAddress, false);
return Collections.singletonList(MDSALUtil.buildApplyActionsInstruction(actions));
}
* action needs to be replaced with goto instruction.
*/
public static List<Instruction> getExtInterfaceInstructions(IInterfaceManager ifaceMgrRpcService,
- String extInterfaceName, String ipAddress, String macAddress) {
+ ItmRpcService itmRpcService,
+ String extInterfaceName, String ipAddress,
+ String macAddress) {
AtomicInteger tableId = new AtomicInteger(-1);
List<Instruction> instructions = new ArrayList<>();
- List<Action> actions = getActions(ifaceMgrRpcService, extInterfaceName, ipAddress, macAddress);
+ List<Action> actions = getActions(ifaceMgrRpcService, itmRpcService, extInterfaceName, ipAddress, macAddress,
+ false);
actions.removeIf(v -> {
org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = v
.getAction();
if (actionClass instanceof NxActionResubmitRpcAddGroupCase) {
- tableId.set(((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable());
+ tableId.set(((NxActionResubmitRpcAddGroupCase) actionClass).getNxResubmit().getTable().toJava());
return true;
} else {
return false;
return instructions;
}
- /**
- * Install ARP Responder FLOW.
- *
- * @param mdSalManager
- * Reference of MDSAL API RPC that provides API for installing
- * flow
- * @param dpnId
- * DPN on which flow to be installed
- * @param flowId
- * Uniquely Identifiable Arp Responder Table flow Id
- * @param flowName
- * Readable flow name
- * @param priority
- * Flow Priority
- * @param cookie
- * Flow Cookie
- * @param matches
- * List of Match Criteria for the flow
- * @param instructions
- * List of Instructions for the flow
- */
- public static void installFlow(IMdsalApiManager mdSalManager, BigInteger dpnId, String flowId, String flowName,
- int priority, BigInteger cookie, List<MatchInfo> matches, List<Instruction> instructions) {
- Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ARP_RESPONDER_TABLE, flowId, priority, flowName, 0, 0,
- cookie, matches, instructions);
- mdSalManager.installFlow(dpnId, flowEntity);
- }
-
- /**
- * Remove flow form DPN.
- *
- * @param mdSalManager
- * Reference of MDSAL API RPC that provides API for installing
- * flow
- * @param dpnId
- * DPN form which flow to be removed
- * @param flowId
- * Uniquely Identifiable Arp Responder Table flow Id that is to
- * be removed
- */
- public static void removeFlow(IMdsalApiManager mdSalManager, BigInteger dpnId, String flowId) {
- Flow flowEntity = MDSALUtil.buildFlow(NwConstants.ARP_RESPONDER_TABLE, flowId);
- mdSalManager.removeFlow(dpnId, flowEntity);
- }
-
/**
* Creates Uniquely Identifiable flow Id.
*
* Gateway IP for which ARP Response flow to be installed
* @return Cookie
*/
- public static BigInteger generateCookie(int lportTag, String ipAddress) {
+ public static Uint64 generateCookie(int lportTag, String ipAddress) {
LOG.trace("IPAddress in long {}", ipAddress);
- BigInteger cookie = NwConstants.COOKIE_ARP_RESPONDER.add(BigInteger.valueOf(255))
- .add(BigInteger.valueOf(ipTolong(ipAddress)));
- return cookie.add(BigInteger.valueOf(lportTag));
+ return Uint64.fromLongBits(NwConstants.COOKIE_ARP_RESPONDER.longValue()
+ + 255 + ipTolong(ipAddress) + lportTag);
}
- private static BigInteger buildCookie(short tableId, int arpOpType) {
- return NwConstants.COOKIE_ARP_RESPONDER.add(BigInteger.ONE).add(
- BigInteger.valueOf(tableId).add(BigInteger.valueOf(arpOpType)));
+ private static Uint64 buildCookie(short tableId, int arpOpType) {
+ return Uint64.fromLongBits(NwConstants.COOKIE_ARP_RESPONDER.longValue()
+ + 1 + tableId + arpOpType);
}
private static String buildFlowRef(short tableId, int arpOpType) {
+ (arpOpType == NwConstants.ARP_REQUEST ? "arp.request" : "arp.replay");
}
- public static FlowEntity createArpDefaultFlow(BigInteger dpId, short tableId, int arpOpType,
+ public static FlowEntity createArpDefaultFlow(Uint64 dpId, short tableId, int arpOpType,
Supplier<List<MatchInfo>> matches, Supplier<List<ActionInfo>> actions) {
List<InstructionInfo> instructions = Collections.singletonList(new InstructionApplyActions(actions.get()));
* Action Key
* @return List of Egress Actions
*/
- public static List<Action> getEgressActionsForInterface(IInterfaceManager ifaceMgrRpcService, String ifName,
- int actionCounter) {
- List<ActionInfo> actionInfos = ifaceMgrRpcService.getInterfaceEgressActions(ifName);
- AtomicInteger counter = new AtomicInteger(actionCounter);
- return actionInfos.stream().map(v -> v.buildAction(counter.getAndIncrement())).collect(Collectors.toList());
+ public static List<Action> getEgressActionsForInterface(IInterfaceManager ifaceMgrRpcService,
+ ItmRpcService itmRpcService, String ifName,
+ int actionCounter, boolean isTunnelInterface) {
+ if (isTunnelInterface && ifaceMgrRpcService.isItmDirectTunnelsEnabled()) {
+ try {
+ RpcResult result = itmRpcService.getEgressActionsForTunnel(new GetEgressActionsForTunnelInputBuilder()
+ .setIntfName(ifName).build()).get();
+ Map<ActionKey, Action> listActions = new HashMap<ActionKey, Action>();
+ if (!result.isSuccessful()) {
+ LOG.error("getEgressActionsForInterface: RPC Call to Get egress actions for interface {} "
+ + "returned with Errors {}", ifName, result.getErrors());
+ } else {
+ listActions = ((GetEgressActionsForTunnelOutput) result.getResult()).getAction();
+ }
+ return new ArrayList<Action>(listActions.values());
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("getEgressActionsForInterface: Exception when egress actions for interface {}", ifName, e);
+ }
+ } else {
+ List<ActionInfo> actionInfos = ifaceMgrRpcService.getInterfaceEgressActions(ifName);
+ AtomicInteger counter = new AtomicInteger(actionCounter);
+ return actionInfos.stream().map(v -> v.buildAction(counter.getAndIncrement())).collect(Collectors.toList());
+ }
+ return Collections.emptyList();
}
/**
RpcResult<AllocateIdOutput> rpcResult = result.get();
if (rpcResult.isSuccessful()) {
LOG.trace("Retrieved Group Id is {}", rpcResult.getResult().getIdValue());
- return rpcResult.getResult().getIdValue();
+ return rpcResult.getResult().getIdValue().toJava();
} else {
LOG.warn("RPC Call to Allocate Id returned with Errors {}", rpcResult.getErrors());
}