Merge "OPNFLWPLUG-1062 Include additional LLDP fields in liblldp"
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / extension / MatchExtensionHelper.java
1 /*
2  * Copyright (c) 2014 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.openflow.md.core.extension;
9
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Optional;
14 import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
15 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
16 import org.opendaylight.openflowplugin.extension.api.AugmentTuple;
17 import org.opendaylight.openflowplugin.extension.api.ConvertorFromOFJava;
18 import org.opendaylight.openflowplugin.extension.api.ExtensionAugment;
19 import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
20 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCase;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifPacketIn;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifPacketInBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifSwitchFlowRemoved;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifSwitchFlowRemovedBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStats;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStatsBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchPacketInMessage;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchPacketInMessageBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcOutputFlowStats;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcOutputFlowStatsBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.Extension;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder;
43 import org.opendaylight.yangtools.yang.binding.Augmentable;
44 import org.opendaylight.yangtools.yang.binding.Augmentation;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public final class MatchExtensionHelper {
49
50     private static final Logger LOG = LoggerFactory.getLogger(MatchExtensionHelper.class);
51
52     private MatchExtensionHelper() {
53         throw new IllegalAccessError("singleton enforcement");
54     }
55
56     /**
57      * Injects an extension.
58      *
59      * @param matchEntry match entry
60      * @param ofVersion openflow version
61      * @param matchPath match path
62      */
63     public static void injectExtension(
64             final short ofVersion,
65             final MatchEntry matchEntry,
66             final MatchBuilder matchBuilder,
67             final MatchPath matchPath) {
68
69         final ExtensionListBuilder extBuilder = processExtension(matchEntry, ofVersion, matchPath);
70
71         final GeneralAugMatchNodesNodeTableFlowBuilder builder = Optional
72                 .ofNullable(matchBuilder.augmentation(GeneralAugMatchNodesNodeTableFlow.class))
73                 .map(GeneralAugMatchNodesNodeTableFlowBuilder::new)
74                 .orElse(new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(new ArrayList<>()));
75
76         if (extBuilder != null) {
77             builder.getExtensionList().add(extBuilder.build());
78         } else {
79             LOG.warn("Convertor for {} for version {} with match path {} not found.",
80                     matchEntry, ofVersion, matchPath.name());
81         }
82
83         matchBuilder.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, builder.build());
84     }
85
86     /**
87      * Processes all extensions.
88      *
89      * @param matchEntries match entries
90      * @param ofVersion openflow version
91      * @param matchPath match path
92      * @param <E> extension point
93      * @return augmentation wrapper containing augmentation depending on matchPath
94      */
95     @SuppressWarnings("unchecked")
96     public static <E extends Augmentable<E>> AugmentTuple<E> processAllExtensions(Collection<MatchEntry> matchEntries,
97             OpenflowVersion ofVersion, MatchPath matchPath) {
98         List<ExtensionList> extensionsList = new ArrayList<>();
99
100         for (MatchEntry matchEntry : matchEntries) {
101             ExtensionListBuilder extensionListBld = processExtension(matchEntry, ofVersion.getVersion(), matchPath);
102             if (extensionListBld == null) {
103                 continue;
104             }
105
106             extensionsList.add(extensionListBld.build());
107         }
108
109         AugmentTuple<E> augmentTuple = null;
110         if (!extensionsList.isEmpty()) {
111             switch (matchPath) {
112                 case FLOWS_STATISTICS_UPDATE_MATCH:
113                     GeneralAugMatchNotifUpdateFlowStatsBuilder generalExtMatchAugBld1 =
114                             new GeneralAugMatchNotifUpdateFlowStatsBuilder();
115                     generalExtMatchAugBld1.setExtensionList(extensionsList);
116                     augmentTuple = (AugmentTuple<E>)
117                             new AugmentTuple<>(
118                                     GeneralAugMatchNotifUpdateFlowStats.class, generalExtMatchAugBld1.build());
119                     break;
120                 case PACKET_RECEIVED_MATCH:
121                     GeneralAugMatchNotifPacketInBuilder generalExtMatchAugBld2 =
122                             new GeneralAugMatchNotifPacketInBuilder();
123                     generalExtMatchAugBld2.setExtensionList(extensionsList);
124                     augmentTuple = (AugmentTuple<E>)
125                             new AugmentTuple<>(GeneralAugMatchNotifPacketIn.class, generalExtMatchAugBld2.build());
126                     break;
127                 case PACKET_IN_MESSAGE_MATCH:
128                     GeneralAugMatchPacketInMessageBuilder generalExtMatchAugBld5 =
129                             new GeneralAugMatchPacketInMessageBuilder();
130                     generalExtMatchAugBld5.setExtensionList(extensionsList);
131                     augmentTuple = (AugmentTuple<E>)
132                             new AugmentTuple<>(GeneralAugMatchPacketInMessage.class, generalExtMatchAugBld5.build());
133                     break;
134                 case SWITCH_FLOW_REMOVED_MATCH:
135                     GeneralAugMatchNotifSwitchFlowRemovedBuilder generalExtMatchAugBld3 =
136                             new GeneralAugMatchNotifSwitchFlowRemovedBuilder();
137                     generalExtMatchAugBld3.setExtensionList(extensionsList);
138                     augmentTuple = (AugmentTuple<E>)
139                             new AugmentTuple<>(
140                                     GeneralAugMatchNotifSwitchFlowRemoved.class, generalExtMatchAugBld3.build());
141                     break;
142                 case FLOWS_STATISTICS_RPC_MATCH:
143                     GeneralAugMatchRpcOutputFlowStatsBuilder generalExtMatchAugBld4 =
144                            new GeneralAugMatchRpcOutputFlowStatsBuilder();
145                     generalExtMatchAugBld4.setExtensionList(extensionsList);
146                     augmentTuple = (AugmentTuple<E>)
147                             new AugmentTuple<>(
148                                     GeneralAugMatchRpcOutputFlowStats.class, generalExtMatchAugBld4.build());
149                     break;
150                 default:
151                     LOG.warn("matchPath not supported: {}", matchPath);
152             }
153         }
154
155         return augmentTuple;
156     }
157
158     /**
159      * Processes an extension.
160      *
161      * @param ofVersion openflow version
162      * @param matchPath match path
163      * @param matchEntry match entry
164      * @return an ExtensionListBuilder
165      */
166     private static ExtensionListBuilder processExtension(MatchEntry matchEntry, short ofVersion, MatchPath matchPath) {
167         ExtensionListBuilder extListBld = null;
168
169         // TODO: EXTENSION PROPOSAL (match, OFJava to MD-SAL)
170         MatchEntrySerializerKey<? extends OxmClassBase, ? extends MatchField> key = new MatchEntrySerializerKey<>(
171                 ofVersion, matchEntry.getOxmClass(), matchEntry.getOxmMatchField());
172
173         // If entry is experimenter, set experimenter ID to key
174         if (matchEntry.getOxmClass().equals(ExperimenterClass.class)) {
175             ExperimenterIdCase experimenterIdCase = (ExperimenterIdCase) matchEntry.getMatchEntryValue();
176             Long experimenterId = experimenterIdCase.getExperimenter().getExperimenter().getValue();
177             key.setExperimenterId(experimenterId);
178         }
179
180         if (null != OFSessionUtil.getExtensionConvertorProvider()) {
181             ConvertorFromOFJava<MatchEntry, MatchPath> convertor =
182                     OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
183             if (convertor != null) {
184                 ExtensionAugment<? extends Augmentation<Extension>> extensionMatch =
185                         convertor.convert(matchEntry, matchPath);
186                 ExtensionBuilder extBld = new ExtensionBuilder();
187                 extBld.addAugmentation(extensionMatch.getAugmentationClass(), extensionMatch.getAugmentationObject());
188
189                 extListBld = new ExtensionListBuilder();
190                 extListBld.setExtension(extBld.build());
191                 extListBld.setExtensionKey(extensionMatch.getKey());
192             }
193         }
194         return extListBld;
195     }
196 }