38ac536993753c016ca2191256e87c74049bf872
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / interfaces / acl / ingress / AceEthWriter.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
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
17 package io.fd.honeycomb.translate.v3po.interfaces.acl.ingress;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20
21 import com.google.common.annotations.VisibleForTesting;
22 import io.fd.honeycomb.translate.vpp.util.MacTranslator;
23 import java.util.List;
24 import javax.annotation.Nonnull;
25 import javax.annotation.Nullable;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth;
28 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
29 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
30 import io.fd.vpp.jvpp.core.dto.InputAclSetInterface;
31 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.InterfaceMode;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 final class AceEthWriter extends AbstractAceWriter<AceEth> implements MacTranslator {
37
38     @VisibleForTesting
39     static final int MATCH_N_VECTORS = 1;
40     private static final Logger LOG = LoggerFactory.getLogger(AceEthWriter.class);
41
42     public AceEthWriter(@Nonnull final FutureJVppCore futureJVppCore) {
43         super(futureJVppCore);
44     }
45
46     private static void checkInterfaceMode(@Nullable final InterfaceMode mode) {
47         checkArgument(InterfaceMode.L2.equals(mode), "L2 rules are not allowed for interface in L3 mode");
48     }
49
50     @Override
51     public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action,
52                                                    @Nonnull final AceEth aceEth,
53                                                    @Nullable final InterfaceMode mode,
54                                                    final int nextTableIndex,
55                                                    final int vlanTags) {
56         checkInterfaceMode(mode);
57
58         final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex);
59
60         request.mask = new byte[16];
61         boolean aceIsEmpty = true;
62
63         // destination-mac-address or destination-mac-address-mask is present =>
64         // ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00:00:00
65         if (aceEth.getDestinationMacAddressMask() != null) {
66             aceIsEmpty = false;
67             final String macAddress = aceEth.getDestinationMacAddressMask().getValue();
68             final List<String> parts = COLON_SPLITTER.splitToList(macAddress);
69             int i = 0;
70             for (String part : parts) {
71                 request.mask[i++] = parseHexByte(part);
72             }
73         } else if (aceEth.getDestinationMacAddress() != null) {
74             aceIsEmpty = false;
75             for (int i = 0; i < 6; ++i) {
76                 request.mask[i] = (byte) 0xff;
77             }
78         }
79
80         // source-mac-address or source-mac-address-mask =>
81         // 00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:00:00:00:00
82         if (aceEth.getSourceMacAddressMask() != null) {
83             aceIsEmpty = false;
84             final String macAddress = aceEth.getSourceMacAddressMask().getValue();
85             final List<String> parts = COLON_SPLITTER.splitToList(macAddress);
86             int i = 6;
87             for (String part : parts) {
88                 request.mask[i++] = parseHexByte(part);
89             }
90         } else if (aceEth.getSourceMacAddress() != null) {
91             aceIsEmpty = false;
92             for (int i = 6; i < 12; ++i) {
93                 request.mask[i] = (byte) 0xff;
94             }
95         }
96
97         if (aceIsEmpty) {
98             throw new IllegalArgumentException(
99                     String.format("Ace %s does not define packet field match values", aceEth.toString()));
100         }
101
102         request.skipNVectors = 0;
103         request.matchNVectors = MATCH_N_VECTORS;
104
105         LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceEth, request);
106         return request;
107     }
108
109     @Override
110     public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action,
111                                                        @Nonnull final AceEth aceEth,
112                                                        @Nullable final InterfaceMode mode,
113                                                        final int tableIndex,
114                                                        final int vlanTags) {
115         checkInterfaceMode(mode);
116
117         final ClassifyAddDelSession request = createClassifySession(action, tableIndex);
118
119         request.match = new byte[16];
120         boolean noMatch = true;
121
122         if (aceEth.getDestinationMacAddress() != null) {
123             noMatch = false;
124             final String macAddress = aceEth.getDestinationMacAddress().getValue();
125             final List<String> parts = COLON_SPLITTER.splitToList(macAddress);
126             int i = 0;
127             for (String part : parts) {
128                 request.match[i++] = parseHexByte(part);
129             }
130         }
131
132         if (aceEth.getSourceMacAddress() != null) {
133             noMatch = false;
134             final String macAddress = aceEth.getSourceMacAddress().getValue();
135             final List<String> parts = COLON_SPLITTER.splitToList(macAddress);
136             int i = 6;
137             for (String part : parts) {
138                 request.match[i++] = parseHexByte(part);
139             }
140         }
141
142         if (noMatch) {
143             throw new IllegalArgumentException(
144                     String.format("Ace %s does not define neither source nor destination MAC address",
145                             aceEth.toString()));
146         }
147
148         LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceEth, request);
149         return request;
150     }
151
152     @Override
153     protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) {
154         request.l2TableIndex = tableIndex;
155     }
156 }