Move adsal into its own subdirectory.
[controller.git] / opendaylight / adsal / sal / api / src / main / java / org / opendaylight / controller / sal / action / PushVlan.java
1 /*
2  * Copyright (c) 2013-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
9 package org.opendaylight.controller.sal.action;
10
11 import javax.xml.bind.annotation.XmlAccessType;
12 import javax.xml.bind.annotation.XmlAccessorType;
13 import javax.xml.bind.annotation.XmlElement;
14 import javax.xml.bind.annotation.XmlRootElement;
15
16 import org.opendaylight.controller.sal.utils.EtherTypes;
17
18 /**
19  * Insert a 802.1q (outermost) header action Execute it multiple times to
20  * achieve QinQ
21  *
22  * 802.1q = [TPID(16) + TCI(16)] TCI = [PCP(3) + CFI(1) + VID(12)]
23  */
24 @XmlRootElement
25 @XmlAccessorType(XmlAccessType.NONE)
26 public class PushVlan extends Action {
27     private static final long serialVersionUID = 1L;
28     private int tag; // TPID - 16 bits
29     private int pcp; // PCP - 3 bits
30     private int cfi; // CFI - 1 bit (drop eligible)
31     private int vlanId; // VID - 12 bits
32     private transient int tci; // TCI = [PCP + CFI + VID] - 16 bits
33     private transient int header; // full 802.1q header [TPID + TCI] - 32 bits
34
35     /* Dummy constructor for JAXB */
36     @SuppressWarnings("unused")
37     private PushVlan() {
38     }
39
40     public PushVlan(int tag, int pcp, int cfi, int vlanId) {
41         type = ActionType.PUSH_VLAN;
42         this.tag = tag;
43         this.cfi = cfi;
44         this.pcp = pcp;
45         this.vlanId = vlanId;
46         this.tci = createTci();
47         this.header = createHeader();
48         runChecks();
49     }
50
51     public PushVlan(EtherTypes tag, int pcp, int cfi, int vlanId) {
52         type = ActionType.PUSH_VLAN;
53         this.tag = tag.intValue();
54         this.cfi = cfi;
55         this.pcp = pcp;
56         this.vlanId = vlanId;
57         this.tci = createTci();
58         this.header = createHeader();
59         runChecks();
60     }
61
62     /**
63      * Construct a new action instance which represents OF 1.3 PUSH_VLAN.
64      *
65      * @param tag  An {@link EtherTypes} instance.
66      */
67     public PushVlan(EtherTypes tag) {
68         this(tag.intValue());
69     }
70
71     /**
72      * Construct a new action instance which represents OF 1.3 PUSH_VLAN.
73      *
74      * @param tag  An ethernet type of a new VLAN tag.
75      */
76     public PushVlan(int tag) {
77         type = ActionType.PUSH_VLAN;
78         this.tag = tag;
79
80         if (tag != EtherTypes.VLANTAGGED.intValue() &&
81             tag != EtherTypes.QINQ.intValue()) {
82             // pass a value which will tell fail and tell something about the
83             // original wrong value
84             checkValue(ActionType.SET_DL_TYPE, 0xBAD << 16 | tag);
85         }
86     }
87
88     private int createTci() {
89         return (pcp & 0x7) << 13 | (cfi & 0x1) << 12 | (vlanId & 0xfff);
90     }
91
92     private int createHeader() {
93         return (tag & 0xffff) << 16 | (pcp & 0x7) << 13 | (cfi & 0x1) << 12 | (vlanId & 0xfff);
94     }
95
96     private void runChecks() {
97         checkValue(ActionType.SET_DL_TYPE, tag);
98         checkValue(ActionType.SET_VLAN_PCP, pcp);
99         checkValue(ActionType.SET_VLAN_CFI, cfi);
100         checkValue(ActionType.SET_VLAN_ID, vlanId);
101         checkValue(tci);
102
103         // Run action specific check which cannot be run by parent
104         if (tag != EtherTypes.VLANTAGGED.intValue() && tag != EtherTypes.QINQ.intValue()
105                 && tag != EtherTypes.OLDQINQ.intValue() && tag != EtherTypes.CISCOQINQ.intValue()) {
106             // pass a value which will tell fail and tell something about the
107             // original wrong value
108             checkValue(ActionType.SET_DL_TYPE, 0xBAD << 16 | tag);
109         }
110     }
111
112     /**
113      * Returns the VID portion of the 802.1q header this action will insert VID
114      * - (12 bits)
115      *
116      * @return byte[]
117      */
118     public int getVlanId() {
119         return vlanId;
120     }
121
122     /**
123      * Returns the CFI portion of the 802.1q header this action will insert CFI
124      * - (1 bit)
125      *
126      * @return
127      */
128     public int getCfi() {
129         return cfi;
130     }
131
132     /**
133      * Returns the vlan PCP portion of the 802.1q header this action will insert
134      * PCP - (3 bits)
135      *
136      * @return byte[]
137      */
138     public int getPcp() {
139         return pcp;
140     }
141
142     /**
143      * Returns the TPID portion of the 802.1q header this action will insert
144      * TPID - (16 bits)
145      */
146     public int getTag() {
147         return tag;
148     }
149
150     /**
151      * Returns the TCI portion of the 802.1q header this action will insert TCI
152      * = [PCP + CFI + VID] - (16 bits)
153      *
154      * @return
155      */
156     public int getTci() {
157         return tci;
158     }
159
160     /**
161      * Returns the full 802.1q header this action will insert header = [TPID +
162      * TIC] (32 bits)
163      *
164      * @return int
165      */
166     @XmlElement(name = "VlanHeader")
167     public int getHeader() {
168         return header;
169     }
170
171     @Override
172     public boolean equals(Object obj) {
173         if (this == obj) {
174             return true;
175         }
176         if (!super.equals(obj)) {
177             return false;
178         }
179         if (getClass() != obj.getClass()) {
180             return false;
181         }
182         PushVlan other = (PushVlan) obj;
183         if (cfi != other.cfi) {
184             return false;
185         }
186         if (pcp != other.pcp) {
187             return false;
188         }
189         if (tag != other.tag) {
190             return false;
191         }
192         if (vlanId != other.vlanId) {
193             return false;
194         }
195         return true;
196     }
197
198     @Override
199     public int hashCode() {
200         final int prime = 31;
201         int result = super.hashCode();
202         result = prime * result + cfi;
203         result = prime * result + pcp;
204         result = prime * result + tag;
205         result = prime * result + vlanId;
206         return result;
207     }
208
209     @Override
210     public String toString() {
211         return type + "[tag = " + tag + ", pcp = " + pcp + ", cfi = " + cfi + ", vlanId = " + vlanId + "]";
212     }
213
214 }