<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>openflowplugin-parent</artifactId>
- <version>0.18.0-SNAPSHOT</version>
- <relativePath>../../parent</relativePath>
- </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-parent</artifactId>
+ <version>0.18.0-SNAPSHOT</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>table-miss-enforcer</artifactId>
- <packaging>bundle</packaging>
+ <groupId>org.opendaylight.openflowplugin.applications</groupId>
+ <artifactId>table-miss-enforcer</artifactId>
+ <packaging>bundle</packaging>
- <dependencies>
- <dependency>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>openflowplugin-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin</groupId>
- <artifactId>openflowplugin-common</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.opendaylight.mdsal</groupId>
- <artifactId>mdsal-binding-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.model</groupId>
- <artifactId>model-inventory</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.model</groupId>
- <artifactId>model-flow-service</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.infrautils</groupId>
- <artifactId>infrautils-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.opendaylight.openflowplugin.applications</groupId>
- <artifactId>device-ownership-service</artifactId>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>com.guicedee.services</groupId>
+ <artifactId>javax.inject</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.infrautils</groupId>
+ <artifactId>infrautils-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.applications</groupId>
+ <artifactId>device-ownership-service</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.component.annotations</artifactId>
+ </dependency>
+ </dependencies>
</project>
import static java.util.Objects.requireNonNull;
import java.util.Collection;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
import org.opendaylight.mdsal.binding.api.DataBroker;
import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.applications.deviceownershipservice.DeviceOwnershipService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
import org.opendaylight.yangtools.yang.common.Uint16;
import org.opendaylight.yangtools.yang.common.Uint64;
import org.opendaylight.yangtools.yang.common.Uint8;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class LLDPPacketPuntEnforcer implements AutoCloseable, ClusteredDataTreeChangeListener<FlowCapableNode> {
+@Singleton
+@Component(service = { })
+public final class LLDPPacketPuntEnforcer implements AutoCloseable, ClusteredDataTreeChangeListener<FlowCapableNode> {
private static final Logger LOG = LoggerFactory.getLogger(LLDPPacketPuntEnforcer.class);
private static final Uint8 TABLE_ID = Uint8.ZERO;
private static final String LLDP_PUNT_WHOLE_PACKET_FLOW = "LLDP_PUNT_WHOLE_PACKET_FLOW";
private static final String DEFAULT_FLOW_ID = "42";
- private final SalFlowService flowService;
- private final DataBroker dataBroker;
private final DeviceOwnershipService deviceOwnershipService;
- private Registration listenerRegistration;
+ private final Registration listenerRegistration;
+ private final AddFlow addFlow;
- public LLDPPacketPuntEnforcer(final SalFlowService flowService, final DataBroker dataBroker,
- final DeviceOwnershipService deviceOwnershipService) {
- this.flowService = flowService;
- this.dataBroker = dataBroker;
- this.deviceOwnershipService = requireNonNull(deviceOwnershipService, "DeviceOwnershipService can not be null");
- }
-
- public void start() {
+ @Inject
+ @Activate
+ public LLDPPacketPuntEnforcer(@Reference final DataBroker dataBroker,
+ @Reference final DeviceOwnershipService deviceOwnershipService,
+ @Reference final RpcConsumerRegistry rpcService) {
+ this.deviceOwnershipService = requireNonNull(deviceOwnershipService);
+ addFlow = rpcService.getRpc(AddFlow.class);
listenerRegistration = dataBroker.registerDataTreeChangeListener(
DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class)),
this);
}
+ @PreDestroy
+ @Deactivate
@Override
public void close() {
- if (listenerRegistration != null) {
- listenerRegistration.close();
- }
+ listenerRegistration.close();
}
@Override
public void onDataTreeChanged(final Collection<DataTreeModification<FlowCapableNode>> modifications) {
- for (DataTreeModification<FlowCapableNode> modification : modifications) {
+ for (var modification : modifications) {
if (modification.getRootNode().getModificationType() == ModificationType.WRITE) {
- String nodeId = modification.getRootPath().getRootIdentifier()
+ final var nodeId = modification.getRootPath().getRootIdentifier()
.firstKeyOf(Node.class).getId().getValue();
if (deviceOwnershipService.isEntityOwned(nodeId)) {
- AddFlowInputBuilder addFlowInput = new AddFlowInputBuilder(createFlow());
- addFlowInput.setNode(new NodeRef(modification.getRootPath()
- .getRootIdentifier().firstIdentifierOf(Node.class)));
- LoggingFutures.addErrorLogging(flowService.addFlow(addFlowInput.build()), LOG, "addFlow");
+ LoggingFutures.addErrorLogging(addFlow.invoke(new AddFlowInputBuilder(createFlow())
+ .setNode(new NodeRef(modification.getRootPath()
+ .getRootIdentifier().firstIdentifierOf(Node.class)))
+ .build()), LOG, "addFlow");
} else {
LOG.debug("Node {} is not owned by this controller, so skip adding LLDP table miss flow", nodeId);
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
- odl:use-default-for-reference-types="true">
-
- <reference id="dataBroker" interface="org.opendaylight.mdsal.binding.api.DataBroker"/>
- <reference id="deviceOwnershipService" interface="org.opendaylight.openflowplugin.applications.deviceownershipservice.DeviceOwnershipService"/>
-
- <odl:rpc-service id="flowService" interface="org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService"/>
-
- <bean id="LLDPPacketPuntEnforcer" class="org.opendaylight.openflowplugin.applications.tablemissenforcer.LLDPPacketPuntEnforcer"
- init-method="start" destroy-method="close">
- <argument ref="flowService"/>
- <argument ref="dataBroker"/>
- <argument ref="deviceOwnershipService"/>
- </bean>
-</blueprint>
import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
+import org.opendaylight.mdsal.binding.api.RpcConsumerRegistry;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.openflowplugin.applications.deviceownershipservice.DeviceOwnershipService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.common.Uint16;
*/
@RunWith(MockitoJUnitRunner.class)
public class LLDPDataTreeChangeListenerTest {
- private LLDPPacketPuntEnforcer lldpPacketPuntEnforcer;
private static final InstanceIdentifier<Node> NODE_IID = InstanceIdentifier.create(Nodes.class)
.child(Node.class, new NodeKey(new NodeId("testnode:1")));
@Mock
- private SalFlowService flowService;
+ private DataBroker dataBroker;
+ @Mock
+ private ListenerRegistration<?> reg;
+ @Mock
+ private RpcConsumerRegistry rpcService;
+ @Mock
+ private AddFlow addFlow;
@Mock
private DataTreeModification<FlowCapableNode> dataTreeModification;
@Mock
@Captor
private ArgumentCaptor<AddFlowInput> addFlowInputCaptor;
+ private LLDPPacketPuntEnforcer lldpPacketPuntEnforcer;
+
@Before
public void setUp() {
- doReturn(RpcResultBuilder.success().buildFuture()).when(flowService).addFlow(any());
- lldpPacketPuntEnforcer = new LLDPPacketPuntEnforcer(flowService, mock(DataBroker.class),
- deviceOwnershipService);
+ doReturn(reg).when(dataBroker).registerDataTreeChangeListener(any(), any());
+ doReturn(RpcResultBuilder.success().buildFuture()).when(addFlow).invoke(any());
+ doReturn(addFlow).when(rpcService).getRpc(any());
+ lldpPacketPuntEnforcer = new LLDPPacketPuntEnforcer(dataBroker, deviceOwnershipService, rpcService);
final DataTreeIdentifier<FlowCapableNode> identifier = DataTreeIdentifier.create(
LogicalDatastoreType.OPERATIONAL, NODE_IID.augmentation(FlowCapableNode.class));
when(dataTreeModification.getRootPath()).thenReturn(identifier);
@Test
public void testOnDataTreeChanged() {
lldpPacketPuntEnforcer.onDataTreeChanged(Collections.singleton(dataTreeModification));
- verify(flowService).addFlow(addFlowInputCaptor.capture());
+ verify(addFlow).invoke(addFlowInputCaptor.capture());
AddFlowInput captured = addFlowInputCaptor.getValue();
assertEquals(NODE_IID, captured.getNode().getValue());
}