blob: c4e8b5c4f61ff063e242ff254429fe6e701d9aea [file] [log] [blame]
Rich Lanecc327672014-04-10 13:37:35 -07001:: # Copyright 2014, Big Switch Networks, Inc.
2:: #
3:: # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4:: # the following special exception:
5:: #
6:: # LOXI Exception
7:: #
8:: # As a special exception to the terms of the EPL, you may distribute libraries
9:: # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10:: # that copyright and licensing notices generated by LoxiGen are not altered or removed
11:: # from the LoxiGen Libraries and the notice provided below is (i) included in
12:: # the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13:: # documentation for the LoxiGen Libraries, if distributed in binary form.
14:: #
15:: # Notice: "Copyright 2014, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16:: #
17:: # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18:: # a copy of the EPL at:
19:: #
20:: # http://www.eclipse.org/legal/epl-v10.html
21:: #
22:: # Unless required by applicable law or agreed to in writing, software
23:: # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24:: # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25:: # EPL for the specific language governing permissions and limitations
26:: # under the EPL.
27::
28:: include('_copyright.c')
29:: import loxi_globals
Rich Lane18391592014-04-10 15:27:00 -070030:: from loxi_ir import *
Rich Lanecc327672014-04-10 13:37:35 -070031
32/**
33 *
34 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
35 *
36 * Source file for OpenFlow message validation.
37 *
38 */
39
40#include "loci_log.h"
41#include <loci/loci.h>
42#include <loci/loci_validator.h>
43
44#define VALIDATOR_LOG(...) LOCI_LOG_ERROR("Validator Error: " __VA_ARGS__)
45
Rich Laned7692fc2014-04-10 16:21:38 -070046:: raw_validator_name = lambda cls, version: "loci_validate_%s_%s" % (cls, version.constant_version(prefix='OF_VERSION_'))
Rich Lane18391592014-04-10 15:27:00 -070047:: validator_name = lambda ofclass: "loci_validate_%s_%s" % (ofclass.name, ofclass.protocol.version.constant_version(prefix='OF_VERSION_'))
48
49/* Forward declarations */
50:: for version, proto in loxi_globals.ir.items():
51:: for ofclass in proto.classes:
Rich Laned7692fc2014-04-10 16:21:38 -070052static int __attribute__((unused)) ${validator_name(ofclass)}(uint8_t *data, int len, int *out_len);
Rich Lane18391592014-04-10 15:27:00 -070053:: #endfor
54:: #endfor
55
56:: readers = { 1: 'buf_u8_get', 2: 'buf_u16_get', 4: 'buf_u32_get' }
57:: types = { 1: 'uint8_t', 2: 'uint16_t', 4: 'uint32_t' }
58
59:: for version, proto in loxi_globals.ir.items():
Rich Laned7692fc2014-04-10 16:21:38 -070060
61:: # Identify classes in lists and generate list validators
62:: seen_lists = set()
63:: for ofclass in proto.classes:
64:: for m in ofclass.members:
65:: if type(m) == OFDataMember and m.oftype.startswith('list'):
66:: element_name = m.oftype[8:-3]
67:: if element_name in seen_lists:
68:: continue
69:: #endif
70:: seen_lists.add(element_name)
71:: list_validator_name = raw_validator_name('of_list_' + element_name, version)
72static int __attribute__((unused))
73${list_validator_name}(uint8_t *data, int len, int *out_len)
74{
75 while (len > 0) {
76 int cur_len = 0xffff;
77 if (${raw_validator_name('of_' + element_name, version)}(data, len, &cur_len) < 0) {
78 return -1;
79 }
80 len -= cur_len;
81 data += cur_len;
82 }
83
84 return 0;
85}
86
87:: #endif
88:: #endfor
89:: #endfor
90
Rich Lane18391592014-04-10 15:27:00 -070091:: for ofclass in proto.classes:
92static int
Rich Laned7692fc2014-04-10 16:21:38 -070093${validator_name(ofclass)}(uint8_t *data, int len, int *out_len)
Rich Lane18391592014-04-10 15:27:00 -070094{
95 if (len < ${ofclass.base_length}) {
96 return -1;
97 }
98
Rich Laned7692fc2014-04-10 16:21:38 -070099:: if ofclass.is_fixed_length:
100 len = ${ofclass.base_length};
101:: #endif
102
Rich Lane18391592014-04-10 15:27:00 -0700103:: # Read and validate length fields
Rich Laned7692fc2014-04-10 16:21:38 -0700104:: field_length_members = {}
Rich Lane18391592014-04-10 15:27:00 -0700105:: for m in ofclass.members:
106:: if type(m) == OFLengthMember:
107 ${types[m.length]} wire_len;
108 ${readers[m.length]}(data + ${m.offset}, &wire_len);
109 if (wire_len > len || wire_len < ${ofclass.base_length}) {
110 return -1;
111 }
112
Rich Lane6cab2bb2014-05-02 13:05:24 -0700113:: if not ofclass.is_fixed_length:
Rich Lane18391592014-04-10 15:27:00 -0700114 len = wire_len;
Rich Lanef3575712014-04-10 17:37:05 -0700115
Rich Lane6cab2bb2014-05-02 13:05:24 -0700116:: #endif
117::
Rich Laned7692fc2014-04-10 16:21:38 -0700118:: elif type(m) == OFFieldLengthMember:
Rich Lanef3575712014-04-10 17:37:05 -0700119:: # Read field length members
Rich Laned7692fc2014-04-10 16:21:38 -0700120:: field_length_members[m.field_name] = m
Rich Lanef3575712014-04-10 17:37:05 -0700121 ${types[m.length]} wire_len_${m.field_name};
122 ${readers[m.length]}(data + ${m.offset}, &wire_len_${m.field_name});
123
Rich Lane18391592014-04-10 15:27:00 -0700124:: #endif
125:: #endfor
126
127:: # Dispatch to subclass validators
128:: if ofclass.virtual:
129:: discriminator = ofclass.discriminator
130 ${types[discriminator.length]} wire_type;
131 ${readers[discriminator.length]}(data + ${discriminator.offset}, &wire_type);
132 switch (wire_type) {
133:: for subclass in proto.classes:
134:: if subclass.superclass == ofclass:
Rich Lanea3c0a482014-04-23 14:23:09 -0700135 case ${hex(subclass.member_by_name(discriminator.name).value)}:
Rich Laned7692fc2014-04-10 16:21:38 -0700136 return ${validator_name(subclass)}(data, len, out_len);
Rich Lane18391592014-04-10 15:27:00 -0700137:: #endif
138:: #endfor
139 }
140:: #endif
141
Rich Laned7692fc2014-04-10 16:21:38 -0700142:: for m in ofclass.members:
Rich Lanef3575712014-04-10 17:37:05 -0700143:: # Validate field-length members
144:: if type(m) == OFDataMember and m.name in field_length_members and m.offset is not None:
145 if (${m.offset} + wire_len_${m.name} > len) {
146 return -1;
147 }
148
149:: #endif
Rich Lane4fe0f772014-04-10 18:28:39 -0700150:: if type(m) == OFDataMember and m.oftype.startswith('list'):
151:: # Validate lists
152:: if m.offset is None:
153 // TODO validate non fixed offset member ${m.name}
154:: continue
155:: #endif
Rich Lane12181e12014-04-10 17:39:27 -0700156:: if not m.name in field_length_members:
157 int wire_len_${m.name} = len - ${m.offset};
Rich Laned7692fc2014-04-10 16:21:38 -0700158:: #endif
159:: element_name = m.oftype[8:-3]
160:: list_validator_name = raw_validator_name('of_list_' + element_name, version)
Rich Lane12181e12014-04-10 17:39:27 -0700161 if (${list_validator_name}(data + ${m.offset}, wire_len_${m.name}, out_len) < 0) {
Rich Laned7692fc2014-04-10 16:21:38 -0700162 return -1;
163 }
164
Rich Lane4fe0f772014-04-10 18:28:39 -0700165:: elif type(m) == OFDataMember and m.oftype == "of_match_t":
166 // TODO validate of_match_t
167:: elif type(m) == OFDataMember and m.oftype == "of_bsn_vport_t":
168 // TODO validate of_bsn_vport_t
169:: elif type(m) == OFDataMember and m.oftype == "of_meter_config_t":
170 // TODO validate of_meter_config_t
171:: elif type(m) == OFDataMember and m.oftype == "of_meter_features_t":
172 // TODO validate of_meter_features_t
Rich Laned7692fc2014-04-10 16:21:38 -0700173:: #endif
174:: #endfor
175
Rich Laned7692fc2014-04-10 16:21:38 -0700176 *out_len = len;
Rich Lane18391592014-04-10 15:27:00 -0700177 return 0;
178}
179
180:: #endfor
181:: #endfor
182
Rich Lanecc327672014-04-10 13:37:35 -0700183int
184of_validate_message(of_message_t msg, int len)
185{
186 of_version_t version;
187 if (len < OF_MESSAGE_MIN_LENGTH ||
188 len != of_message_length_get(msg)) {
189 VALIDATOR_LOG("message length %d != %d", len,
190 of_message_length_get(msg));
191 return -1;
192 }
193
194 version = of_message_version_get(msg);
Rich Laned7692fc2014-04-10 16:21:38 -0700195 int out_len;
Rich Lanecc327672014-04-10 13:37:35 -0700196 switch (version) {
197:: for version, proto in loxi_globals.ir.items():
198 case ${version.constant_version(prefix='OF_VERSION_')}:
Rich Laned7692fc2014-04-10 16:21:38 -0700199 return ${validator_name(proto.class_by_name('of_header'))}(msg, len, &out_len);
Rich Lanecc327672014-04-10 13:37:35 -0700200:: #endfor
201 default:
Rich Lane2dd17012014-10-16 09:55:10 -0700202 VALIDATOR_LOG("Bad version %d", version);
Rich Lanecc327672014-04-10 13:37:35 -0700203 return -1;
204 }
205}