import java.util.Collection;
import java.util.Collections;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.openflowplugin.openflow.md.core.MDController;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManagerImpl;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionConverterManager;
+import org.opendaylight.openflowplugin.openflow.md.lldp.LLDPPAcketPuntEnforcer;
import org.opendaylight.openflowplugin.statistics.MessageCountCommandProvider;
import org.opendaylight.openflowplugin.statistics.MessageCountDumper;
import org.opendaylight.openflowplugin.statistics.MessageObservatory;
import org.opendaylight.openflowplugin.statistics.MessageSpyCounterImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+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.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
LOG.debug("onSessionInitiated");
registrationManager = new SalRegistrationManager();
registrationManager.onSessionInitiated(session);
+ //TODO : LLDPPAcketPuntEnforcer should be instantiated and registered in separate module driven by config subsystem
+ InstanceIdentifier path = InstanceIdentifier.create(Nodes.class).child(Node.class);
+ registrationManager.getSessionManager().getDataBroker().registerDataChangeListener(
+ LogicalDatastoreType.OPERATIONAL,
+ path,
+ new LLDPPAcketPuntEnforcer(
+ session.<SalFlowService>getRpcService(SalFlowService.class)),
+ AsyncDataBroker.DataChangeScope.BASE);
mdController = new MDController();
mdController.setSwitchConnectionProviders(switchConnectionProviders);
mdController.setMessageSpyCounter(messageCountProvider);
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.lldp;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.openflowplugin.openflow.md.OFConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+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.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.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Created by Martin Bobak mbobak@cisco.com on 8/27/14.
+ */
+public class LLDPPAcketPuntEnforcer implements DataChangeListener {
+
+ private static final short TABLE_ID = (short) 0;
+ 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;
+
+ public LLDPPAcketPuntEnforcer(SalFlowService flowService) {
+ this.flowService = flowService;
+ }
+
+ @Override
+ public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ final Set<InstanceIdentifier<?>> changedDataKeys = change.getCreatedData().keySet();
+
+ for (InstanceIdentifier<?> key : changedDataKeys) {
+ AddFlowInputBuilder addFlowInput = new AddFlowInputBuilder(createFlow());
+ addFlowInput.setNode(new NodeRef(key));
+ this.flowService.addFlow(addFlowInput.build());
+ }
+ }
+
+
+ protected Flow createFlow() {
+ FlowBuilder flowBuilder = new FlowBuilder();
+ flowBuilder.setMatch(new MatchBuilder().build());
+ flowBuilder.setInstructions(createSendToControllerInstructions().build());
+ flowBuilder.setPriority(0);
+
+ FlowKey key = new FlowKey(new FlowId(DEFAULT_FLOW_ID));
+ flowBuilder.setBarrier(Boolean.FALSE);
+ // flow.setBufferId(new Long(12));
+ BigInteger value = new BigInteger("10", 10);
+ // BigInteger outputPort = new BigInteger("65535", 10);
+ flowBuilder.setCookie(new FlowCookie(value));
+ flowBuilder.setCookieMask(new FlowCookie(value));
+ flowBuilder.setHardTimeout(0);
+ flowBuilder.setIdleTimeout(0);
+ flowBuilder.setInstallHw(false);
+ flowBuilder.setStrict(false);
+ flowBuilder.setContainerName(null);
+ flowBuilder.setFlags(new FlowModFlags(false, false, false, false, true));
+ flowBuilder.setId(new FlowId("12"));
+ flowBuilder.setTableId(TABLE_ID);
+ flowBuilder.setKey(key);
+ flowBuilder.setFlowName(LLDP_PUNT_WHOLE_PACKET_FLOW);
+
+ return flowBuilder.build();
+ }
+
+ private static InstructionsBuilder createSendToControllerInstructions() {
+ List<Action> actionList = new ArrayList<Action>();
+ ActionBuilder ab = new ActionBuilder();
+
+ OutputActionBuilder output = new OutputActionBuilder();
+ output.setMaxLength(OFConstants.OFPCML_NO_BUFFER);
+ Uri value = new Uri(OutputPortValues.CONTROLLER.toString());
+ output.setOutputNodeConnector(value);
+ ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+ ab.setOrder(0);
+ ab.setKey(new ActionKey(0));
+ actionList.add(ab.build());
+ // Create an Apply Action
+ ApplyActionsBuilder aab = new ApplyActionsBuilder();
+ aab.setAction(actionList);
+
+ // Wrap our Apply Action in an Instruction
+ InstructionBuilder ib = new InstructionBuilder();
+ ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
+ ib.setOrder(0);
+ ib.setKey(new InstructionKey(0));
+
+ // Put our Instruction in a list of Instructions
+ InstructionsBuilder isb = new InstructionsBuilder();
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ instructions.add(ib.build());
+ isb.setInstruction(instructions);
+ return isb;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.openflow.md.lldp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
+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.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;
+
+/**
+ * Created by Martin Bobak mbobak@cisco.com on 8/29/14.
+ */
+public class LLDPDataChangeListenerTest {
+
+ @Mock
+ private static SalFlowService flowService;
+
+ /**
+ * Test method for {@link LLDPPAcketPuntEnforcer#createFlow()}
+ * which ensures that LLDPDataChangeListener creates proper flow for
+ */
+ @Test
+ public void testCreateFlow() {
+ LLDPPAcketPuntEnforcer lldpDataChangeListener = new LLDPPAcketPuntEnforcer(flowService);
+ evaluateFlow(lldpDataChangeListener.createFlow());
+ }
+
+ private final void evaluateFlow(Flow flow) {
+ evaluateInstructions(flow.getInstructions());
+ }
+
+ private final void evaluateInstructions(Instructions instructions) {
+ assertNotNull(instructions.getInstruction());
+ assertEquals(1, instructions.getInstruction().size());
+ Instruction instruction = instructions.getInstruction().get(0);
+ evaluateInstruction(instruction);
+ }
+
+ private final void evaluateInstruction(Instruction instruction) {
+ if (instruction.getInstruction() instanceof ApplyActionsCase) {
+ ApplyActionsCase applyActionsCase = (ApplyActionsCase) instruction.getInstruction();
+ assertNotNull(applyActionsCase.getApplyActions().getAction());
+ assertEquals(1, applyActionsCase.getApplyActions().getAction().size());
+ Action action = applyActionsCase.getApplyActions().getAction().get(0);
+ evaluateAction(action);
+ }
+ }
+
+ private final void evaluateAction(Action action) {
+ if (action.getAction() instanceof OutputActionCase) {
+ OutputActionCase outputActionCase = (OutputActionCase) action.getAction();
+ assertEquals("CONTROLLER", outputActionCase.getOutputAction().getOutputNodeConnector().getValue());
+ assertEquals(new Integer(0xffff).intValue(), outputActionCase.getOutputAction().getMaxLength().intValue());
+ }
+ }
+}