Ditch blueprint from of-switch-config-pusher
[openflowplugin.git] / applications / table-miss-enforcer / src / main / java / org / opendaylight / openflowplugin / applications / tablemissenforcer / LLDPPacketPuntEnforcer.java
1 /*
2  * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowplugin.applications.tablemissenforcer;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.util.Collection;
13 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
14 import org.opendaylight.mdsal.binding.api.ClusteredDataTreeChangeListener;
15 import org.opendaylight.mdsal.binding.api.DataBroker;
16 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
17 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.mdsal.binding.api.DataTreeModification;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.openflowplugin.api.OFConstants;
21 import org.opendaylight.openflowplugin.applications.deviceownershipservice.DeviceOwnershipService;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
44 import org.opendaylight.yangtools.concepts.Registration;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
47 import org.opendaylight.yangtools.yang.common.Uint16;
48 import org.opendaylight.yangtools.yang.common.Uint64;
49 import org.opendaylight.yangtools.yang.common.Uint8;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class LLDPPacketPuntEnforcer implements AutoCloseable, ClusteredDataTreeChangeListener<FlowCapableNode> {
54     private static final Logger LOG = LoggerFactory.getLogger(LLDPPacketPuntEnforcer.class);
55     private static final Uint8 TABLE_ID = Uint8.ZERO;
56     private static final String LLDP_PUNT_WHOLE_PACKET_FLOW = "LLDP_PUNT_WHOLE_PACKET_FLOW";
57     private static final String DEFAULT_FLOW_ID = "42";
58
59     private final SalFlowService flowService;
60     private final DataBroker dataBroker;
61     private final DeviceOwnershipService deviceOwnershipService;
62     private Registration listenerRegistration;
63
64     public LLDPPacketPuntEnforcer(final SalFlowService flowService, final DataBroker dataBroker,
65             final DeviceOwnershipService deviceOwnershipService) {
66         this.flowService = flowService;
67         this.dataBroker = dataBroker;
68         this.deviceOwnershipService = requireNonNull(deviceOwnershipService, "DeviceOwnershipService can not be null");
69     }
70
71     public void start() {
72         listenerRegistration = dataBroker.registerDataTreeChangeListener(
73             DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
74                 InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class)),
75             this);
76     }
77
78     @Override
79     public void close() {
80         if (listenerRegistration != null) {
81             listenerRegistration.close();
82         }
83     }
84
85     @Override
86     public void onDataTreeChanged(final Collection<DataTreeModification<FlowCapableNode>> modifications) {
87         for (DataTreeModification<FlowCapableNode> modification : modifications) {
88             if (modification.getRootNode().getModificationType() == ModificationType.WRITE) {
89                 String nodeId = modification.getRootPath().getRootIdentifier()
90                         .firstKeyOf(Node.class).getId().getValue();
91                 if (deviceOwnershipService.isEntityOwned(nodeId)) {
92                     AddFlowInputBuilder addFlowInput = new AddFlowInputBuilder(createFlow());
93                     addFlowInput.setNode(new NodeRef(modification.getRootPath()
94                             .getRootIdentifier().firstIdentifierOf(Node.class)));
95                     LoggingFutures.addErrorLogging(flowService.addFlow(addFlowInput.build()), LOG, "addFlow");
96                 } else {
97                     LOG.debug("Node {} is not owned by this controller, so skip adding LLDP table miss flow", nodeId);
98                 }
99             }
100         }
101     }
102
103     static Flow createFlow() {
104         return new FlowBuilder()
105             .setMatch(new MatchBuilder().build())
106             .setInstructions(createSendToControllerInstructions().build())
107             .setPriority(Uint16.ZERO)
108             .setBarrier(Boolean.FALSE)
109             .setBufferId(OFConstants.OFP_NO_BUFFER)
110             .setCookie(new FlowCookie(Uint64.TEN))
111             .setCookieMask(new FlowCookie(Uint64.TEN))
112             .setHardTimeout(Uint16.ZERO)
113             .setIdleTimeout(Uint16.ZERO)
114             .setInstallHw(false)
115             .setStrict(false)
116             .setContainerName(null)
117             .setFlags(new FlowModFlags(false, false, false, false, true))
118             .setId(new FlowId("12"))
119             .setTableId(TABLE_ID)
120             .withKey(new FlowKey(new FlowId(DEFAULT_FLOW_ID)))
121             .setFlowName(LLDP_PUNT_WHOLE_PACKET_FLOW)
122             .build();
123     }
124
125     private static InstructionsBuilder createSendToControllerInstructions() {
126         return new InstructionsBuilder()
127             .setInstruction(BindingMap.of(new InstructionBuilder()
128                 // Wrap our Apply Action in an Instruction
129                 .setInstruction(new ApplyActionsCaseBuilder()
130                     .setApplyActions(new ApplyActionsBuilder()
131                         // Create an Apply Action
132                         .setAction(BindingMap.of(new ActionBuilder()
133                             .setAction(new OutputActionCaseBuilder()
134                                 .setOutputAction(new OutputActionBuilder()
135                                     .setMaxLength(OFConstants.OFPCML_NO_BUFFER)
136                                     .setOutputNodeConnector(new Uri(OutputPortValues.CONTROLLER.toString()))
137                                     .build())
138                                 .build())
139                             .setOrder(0)
140                             .build()))
141                         .build())
142                     .build())
143                 .setOrder(0)
144                 .build()));
145     }
146 }