blob: d5a025c6cacdef2e9ce46ca9539fa83da89fbff6 [file] [log] [blame]
Laszlo Papp8b3a5f62017-10-05 13:32:00 +01001/*
2 * Copyright 2017 Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.drivers.polatis.netconf;
18
19import org.onosproject.yang.gen.v1.opticalswitch.rev20170804.opticalswitch.CrossConnects;
20import org.onosproject.yang.gen.v1.opticalswitch.rev20170804.opticalswitch.crossconnects.Pair;
21
22import com.google.common.collect.ImmutableList;
23
24import org.apache.commons.configuration.HierarchicalConfiguration;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.driver.AbstractHandlerBehaviour;
27import org.onosproject.net.flow.DefaultFlowEntry;
28import org.onosproject.net.flow.FlowEntry;
29import org.onosproject.net.flow.FlowRule;
30import org.onosproject.net.flow.FlowRuleProgrammable;
31import org.onosproject.netconf.NetconfException;
32import org.slf4j.Logger;
33
34import java.util.Collection;
35import java.util.Date;
36import java.util.List;
37import java.util.stream.Collectors;
38
39import java.text.ParseException;
40import java.text.SimpleDateFormat;
41
42import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.netconfGet;
43import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.netconfEditConfig;
44import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.opticalRevision;
45import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.configsAt;
46import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.xmlOpen;
47import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.xmlClose;
48import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_CONNS;
49import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_CONNS_XMLNS;
50import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.KEY_DATA_CONNS;
Laszlo Papp8b87a192017-10-19 18:47:12 +010051import static org.onosproject.drivers.polatis.netconf.PolatisNetconfUtility.CFG_MODE_MERGE;
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010052import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * Flow rule programmable behaviour for polatis optical netconf devices.
56 */
57public class PolatisFlowRuleProgrammable
58 extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
59
60 public static final String KEY_CHID = "wavelength-id";
61 public static final String KEY_SRC = "ingress";
62 public static final String KEY_DST = "egress";
63 public static final String KEY_SRC_CHID = String.format("%s.%s", KEY_SRC, KEY_CHID);
Laszlo Papp8b3a5f62017-10-05 13:32:00 +010064 public static final String CFG_MODE_DELETE = "delete";
65 public static final String KEY_PAIR = "pair";
66 public static final String KEY_PAIRS = "pairs";
67 public static final String KEY_PAIR_DELETE = String.format("%s %s", KEY_PAIR, CFG_MODE_DELETE);
68 public static final String PAIR_COMPAT_REVISION = "2017-08-04";
69
70 private static final Logger log = getLogger(PolatisFlowRuleProgrammable.class);
71
72 @Override
73 public Collection<FlowEntry> getFlowEntries() {
74 return parseConnections();
75 }
76
77 @Override
78 public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
79 return applyConnections(rules);
80 }
81
82 @Override
83 public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
84 return removeConnections(rules);
85 }
86
87 private String getConnectionsFilter() {
88 return new StringBuilder(xmlOpen(KEY_CONNS_XMLNS))
89 .append(xmlClose(KEY_CONNS))
90 .toString();
91 }
92
93 private Collection<FlowEntry> parseConnections() {
94 log.debug("Fetch connections...");
95 String reply = netconfGet(handler(), getConnectionsFilter());
96 final String keyPairMode = String.format("%s.%s", KEY_DATA_CONNS, parseKeyPairCompat());
97 List<HierarchicalConfiguration> subtrees = configsAt(reply, keyPairMode);
98 ImmutableList.Builder<FlowEntry> connectionsBuilder = ImmutableList.builder();
99 for (HierarchicalConfiguration connection : subtrees) {
100 connectionsBuilder.add(new DefaultFlowEntry(parseConnection(connection), FlowEntry.FlowEntryState.ADDED));
101 }
102 return connectionsBuilder.build();
103 }
104
105 private FlowRule parseConnection(HierarchicalConfiguration cfg) {
106 return PolatisOpticalUtility.toFlowRule(this,
107 PortNumber.portNumber(cfg.getInt(KEY_SRC)),
108 PortNumber.portNumber(cfg.getInt(KEY_DST)));
109 }
110
111 private Collection<FlowRule> applyConnections(Collection<FlowRule> rules) {
112 return rules.stream()
113 .filter(c -> editConnection(c, CFG_MODE_MERGE))
114 .collect(Collectors.toList());
115 }
116
117 private boolean editConnection(FlowRule rule, String mode) {
118 CrossConnects crossConnects = PolatisOpticalUtility.fromFlowRule(this, rule);
119 final StringBuilder cfg = new StringBuilder(xmlOpen(KEY_CONNS_XMLNS));
120 List<Pair> pairs = crossConnects.pair();
121 final String keyPairCompat = parseKeyPairCompat();
122 final String keyPairMode = String.format("%s operation=\"%s\"", keyPairCompat, mode);
123 pairs.forEach(p -> {
124 cfg.append(xmlOpen(keyPairMode))
125 .append(xmlOpen(KEY_SRC))
126 .append(p.ingress())
127 .append(xmlClose(KEY_SRC))
128 .append(xmlOpen(KEY_DST))
129 .append(p.egress())
130 .append(xmlClose(KEY_DST))
131 .append(xmlClose(keyPairCompat));
132 });
133 cfg.append(xmlClose(KEY_CONNS));
134 return netconfEditConfig(handler(), null, cfg.toString());
135 }
136
137 private Collection<FlowRule> removeConnections(Collection<FlowRule> rules) {
138 return rules.stream()
139 .filter(c -> editConnection(c, CFG_MODE_DELETE))
140 .collect(Collectors.toList());
141 }
142
143 private String parseKeyPairCompat() {
144 String rev = opticalRevision(handler());
145 if (rev == null) {
Ray Milkey2b4958a2018-02-06 18:59:06 -0800146 throw new IllegalStateException(new NetconfException("Failed to obtain the revision."));
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100147 }
148 String keyPairCompat;
149 try {
150 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
151 Date date = sdf.parse(PAIR_COMPAT_REVISION);
152
153 if (date.compareTo(sdf.parse(rev)) > 0) {
154 keyPairCompat = KEY_PAIRS;
155 } else {
156 keyPairCompat = KEY_PAIR;
157 }
158 } catch (ParseException e) {
Ray Milkey2b4958a2018-02-06 18:59:06 -0800159 throw new IllegalArgumentException(new NetconfException(String.format("Incorrect date format: %s", rev)));
Laszlo Papp8b3a5f62017-10-05 13:32:00 +0100160 }
161 return keyPairCompat;
162 }
163}