blob: 92846c2e6f5dea36bf6da070988b44b96c38c5b9 [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
113 len = wire_len;
Rich Laned7692fc2014-04-10 16:21:38 -0700114:: elif type(m) == OFFieldLengthMember:
115:: field_length_members[m.field_name] = m
Rich Lane18391592014-04-10 15:27:00 -0700116:: #endif
117:: #endfor
118
119:: # Dispatch to subclass validators
120:: if ofclass.virtual:
121:: discriminator = ofclass.discriminator
122 ${types[discriminator.length]} wire_type;
123 ${readers[discriminator.length]}(data + ${discriminator.offset}, &wire_type);
124 switch (wire_type) {
125:: for subclass in proto.classes:
126:: if subclass.superclass == ofclass:
127 case ${subclass.member_by_name(discriminator.name).value}:
Rich Laned7692fc2014-04-10 16:21:38 -0700128 return ${validator_name(subclass)}(data, len, out_len);
Rich Lane18391592014-04-10 15:27:00 -0700129:: #endif
130:: #endfor
131 }
132:: #endif
133
Rich Laned7692fc2014-04-10 16:21:38 -0700134:: # Validate fixed-offset lists
135:: for m in ofclass.members:
136:: if type(m) == OFDataMember and m.oftype.startswith('list') and m.offset is not None:
137:: if m.name in field_length_members:
138:: continue # TODO handle field length members
139:: #endif
140:: element_name = m.oftype[8:-3]
141:: list_validator_name = raw_validator_name('of_list_' + element_name, version)
142 if (${list_validator_name}(data + ${m.offset}, len - ${m.offset}, out_len) < 0) {
143 return -1;
144 }
145
146:: #endif
147:: #endfor
148
149:: # TODO handle non-fixed-offset lists
150
151 *out_len = len;
Rich Lane18391592014-04-10 15:27:00 -0700152 return 0;
153}
154
155:: #endfor
156:: #endfor
157
Rich Lanecc327672014-04-10 13:37:35 -0700158int
159of_validate_message(of_message_t msg, int len)
160{
161 of_version_t version;
162 if (len < OF_MESSAGE_MIN_LENGTH ||
163 len != of_message_length_get(msg)) {
164 VALIDATOR_LOG("message length %d != %d", len,
165 of_message_length_get(msg));
166 return -1;
167 }
168
169 version = of_message_version_get(msg);
Rich Laned7692fc2014-04-10 16:21:38 -0700170 int out_len;
Rich Lanecc327672014-04-10 13:37:35 -0700171 switch (version) {
172:: for version, proto in loxi_globals.ir.items():
173 case ${version.constant_version(prefix='OF_VERSION_')}:
Rich Laned7692fc2014-04-10 16:21:38 -0700174 return ${validator_name(proto.class_by_name('of_header'))}(msg, len, &out_len);
Rich Lanecc327672014-04-10 13:37:35 -0700175:: #endfor
176 default:
177 VALIDATOR_LOG("Bad version %d", OF_VERSION_1_3);
178 return -1;
179 }
180}