304d6c1f009bf16386a9198196e96825545606e7
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / interfaces / acl / common / Ip4AclTranslator.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.common;
18
19 import com.google.common.primitives.Ints;
20 import io.fd.honeycomb.translate.vpp.util.Ipv4Translator;
21 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession;
22 import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.AclIpHeaderFields;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.AclIpv4HeaderFields;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.InterfaceMode;
27
28 interface Ip4AclTranslator extends Ipv4Translator {
29     int ETHER_TYPE_OFFSET = 12; // first 14 bytes represent L2 header (2x6)
30     int DSCP_OFFSET = 15;
31     int DSCP_MASK = 0xfc;
32
33     int IP_PROTOCOL_OFFSET = ETHER_TYPE_OFFSET + 11;
34     int IP_PROTOCOL_MASK = 0xff;
35
36     int IP4_LEN = 4;
37     int IP4_MASK_BIT_LENGTH = 32;
38     int SRC_IP_OFFSET = ETHER_TYPE_OFFSET + 14;
39     int DST_IP_OFFSET = SRC_IP_OFFSET + IP4_LEN;
40     int SRC_PORT_OFFSET = DST_IP_OFFSET + IP4_LEN;
41     int DST_PORT_OFFSET = SRC_PORT_OFFSET + 2;
42
43     default boolean ip4Mask(final int baseOffset, final InterfaceMode mode, final AclIpHeaderFields header,
44                             final AclIpv4HeaderFields ip4, final ClassifyAddDelTable request) {
45         boolean aceIsEmpty = true;
46         if (InterfaceMode.L2.equals(mode)) {
47             // in L2 mode we need to match ether type
48             request.mask[baseOffset + ETHER_TYPE_OFFSET] = (byte) 0xff;
49             request.mask[baseOffset + ETHER_TYPE_OFFSET + 1] = (byte) 0xff;
50         }
51         if (header.getDscp() != null) {
52             aceIsEmpty = false;
53             request.mask[baseOffset + DSCP_OFFSET] = (byte) DSCP_MASK; // first 6 bits
54         }
55         if (header.getProtocol() != null) { // Internet Protocol number
56             aceIsEmpty = false;
57             request.mask[baseOffset + IP_PROTOCOL_OFFSET] = (byte) IP_PROTOCOL_MASK;
58         }
59         if (header.getSourcePortRange() != null) {
60             // TODO (HONEYCOMB-253): port matching will not work correctly if Options are present
61             aceIsEmpty = false;
62             request.mask[baseOffset + SRC_PORT_OFFSET] = (byte) 0xff;
63             request.mask[baseOffset + SRC_PORT_OFFSET + 1] = (byte) 0xff;
64         }
65         if (header.getDestinationPortRange() != null) {
66             // TODO (HONEYCOMB-253): port matching will not work correctly if Options are present
67             aceIsEmpty = false;
68             request.mask[baseOffset + DST_PORT_OFFSET] = (byte) 0xff;
69             request.mask[baseOffset + DST_PORT_OFFSET + 1] = (byte) 0xff;
70         }
71         if (ip4.getSourceIpv4Network() != null) {
72             aceIsEmpty = false;
73             System.arraycopy(Impl.toByteMask(ip4.getSourceIpv4Network()), 0, request.mask,
74                 baseOffset + SRC_IP_OFFSET, IP4_LEN);
75         }
76         if (ip4.getDestinationIpv4Network() != null) {
77             aceIsEmpty = false;
78             System.arraycopy(Impl.toByteMask(ip4.getDestinationIpv4Network()), 0, request.mask,
79                 baseOffset + DST_IP_OFFSET, IP4_LEN);
80         }
81         return aceIsEmpty;
82     }
83
84     default boolean ip4Match(final int baseOffset, final InterfaceMode mode, final AclIpHeaderFields header,
85                              final AclIpv4HeaderFields ip4, final Integer srcPort,
86                              final Integer dstPort, final ClassifyAddDelSession request) {
87         boolean noMatch = true;
88         if (InterfaceMode.L2.equals(mode)) {
89             // match IP4 etherType (0x0800)
90             request.match[baseOffset + ETHER_TYPE_OFFSET] = 0x08;
91             request.match[baseOffset + ETHER_TYPE_OFFSET + 1] = 0x00;
92         }
93         if (header.getDscp() != null) {
94             noMatch = false;
95             request.match[baseOffset + DSCP_OFFSET] = (byte) (DSCP_MASK & (header.getDscp().getValue() << 2));
96         }
97         if (header.getProtocol() != null) { // Internet Protocol number
98             noMatch = false;
99             request.match[baseOffset + IP_PROTOCOL_OFFSET] = (byte) (IP_PROTOCOL_MASK & header.getProtocol());
100         }
101         if (srcPort != null) {
102             // TODO (HONEYCOMB-253): port matching will not work correctly if Options are present
103             noMatch = false;
104             request.match[baseOffset + SRC_PORT_OFFSET] = (byte) (0xff & srcPort >> 8);
105             request.match[baseOffset + SRC_PORT_OFFSET + 1] = (byte) (0xff & srcPort);
106         }
107         if (header.getDestinationPortRange() != null) {
108             // TODO (HONEYCOMB-253): port matching will not work correctly if Options are present
109             noMatch = false;
110             request.match[baseOffset + DST_PORT_OFFSET] = (byte) (0xff & dstPort >> 8);
111             request.match[baseOffset + DST_PORT_OFFSET + 1] = (byte) (0xff & dstPort);
112         }
113         if (ip4.getSourceIpv4Network() != null) {
114             noMatch = false;
115             System.arraycopy(Impl.toMatchValue(ip4.getSourceIpv4Network()), 0, request.match,
116                 baseOffset + SRC_IP_OFFSET, IP4_LEN);
117
118         }
119         if (ip4.getDestinationIpv4Network() != null) {
120             noMatch = false;
121             System.arraycopy(Impl.toMatchValue(ip4.getDestinationIpv4Network()), 0, request.match,
122                 baseOffset + DST_IP_OFFSET, IP4_LEN);
123
124         }
125         return noMatch;
126     }
127
128     class Impl {
129         private static byte[] toByteMask(final int prefixLength) {
130             final long mask = ((1L << prefixLength) - 1) << (IP4_MASK_BIT_LENGTH - prefixLength);
131             return Ints.toByteArray((int) mask);
132         }
133
134         private static byte[] toByteMask(final Ipv4Prefix ipv4Prefix) {
135             final int prefixLength = Byte.valueOf(ipv4Prefix.getValue().split("/")[1]);
136             return toByteMask(prefixLength);
137         }
138
139         private static byte[] toMatchValue(final Ipv4Prefix ipv4Prefix) {
140             final String[] split = ipv4Prefix.getValue().split("/");
141             final byte[] addressBytes = Ipv4Translator.INSTANCE.ipv4AddressNoZoneToArray(split[0]);
142             final byte[] mask = Impl.toByteMask(Byte.valueOf(split[1]));
143             for (int i = 0; i < addressBytes.length; ++i) {
144                 addressBytes[i] &= mask[i];
145             }
146             return addressBytes;
147         }
148     }
149 }