blob: 33a09489cf1c14b679d24b6048066d4c08572c9b [file] [log] [blame]
Srikanth Vavilapalli1725e492014-12-01 17:50:52 -08001#
2# Copyright (c) 2012,2013 Big Switch Networks, Inc.
3#
4# Licensed under the Eclipse Public License, Version 1.0 (the
5# "License"); you may not use this file except in compliance with the
6# License. You may obtain a copy of the License at
7#
8# http://www.eclipse.org/legal/epl-v10.html
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
13# implied. See the License for the specific language governing
14# permissions and limitations under the License.
15#
16
17import re
18import utif
19
20#
21# VNSW -- any functions used to support vns
22#
23
24def init_vnsw(bs, modi):
25 global sdnsh, mi
26 sdnsh = bs
27 mi = modi
28
29
30MAC_RE = re.compile(r'^(([A-Fa-f\d]){2}:?){5}[A-Fa-f\d]{2}$')
31DIGITS_RE = re.compile(r'^\d+$')
32
33
34#
35# --------------------------------------------------------------------------------
36
37def create_default_vns():
38 """
39 In some situations, for example, when a blank cassandra db/store
40 is having a running-config pushed.
41 """
42 (error, created) = sdnsh.find_or_create_row('vns-definition', 'default')
43 if error:
44 return False
45
46 return True
47
48
49#
50# --------------------------------------------------------------------------------
51
52def associate_foreign_key_for_vns_interface(create_dict):
53 """
54 Association of the foreign key 'rule' for vns-interfaces requires some
55 substantial work, along with additional validation
56 """
57
58 # determine the best candidate for the current rule
59 if not 'interface' in create_dict or not 'vns' in create_dict:
60 return create_dict
61 rule = None
62 items = create_dict['interface'].split('/')
63 mac = None
64 port = None
65 if len(items) == 1:
66 if items[0].startswith('Eth'):
67 rule = items[0][3:]
68 elif items[0].startswith('VEth'):
69 rule = items[0][4:]
70 else:
71 rule = items[0]
72 elif len(items) == 2 and MAC_RE.match(items[1]):
73 mac = items[1]
74 if items[0].startswith('VEth'):
75 rule = items[0][4:]
76 else:
77 rule = items[0]
78 elif len(items) == 2 and DIGITS_RE.match(items[1]):
79 port = items[1]
80 if items[0].startswith('Eth'):
81 rule = items[0][3:]
82 else:
83 rule = items[0]
84 else:
85 # Assume this is some abstract port name
86 port = items[1]
87 rule = items[0]
88
89 if not rule:
90 return create_dict
91
92 if rule and rule == 'default':
93 if not create_default_vns():
94 return
95
96 # try to look up the particular rule
97 rule_id = sdnsh.unique_key_from_non_unique([create_dict['vns'],
98 rule])
99 if_obj_type = 'vns-interface-rule'
100 if_key = mi.pk(if_obj_type)
101 try:
102 row = sdnsh.get_table_from_store(if_obj_type,
103 if_key,
104 rule_id)
105 errors = None
106 except Exception, e:
107 errors = sdnsh.rest_error_to_dict(e)
108 print sdnsh.rest_error_dict_to_message(errors)
109
110 if errors:
111 return create_dict
112
113 #
114 # validate the rule referenced matches the expected
115 # 'id' created here.
116 #
117 if len(row) == 0:
118 return create_dict
119 if_rule = row[0]
120
121 #
122 # Perform various validations to ensure the created interface
123 # would makes sense to sdnplatform
124 rule_is_number = False
125 if DIGITS_RE.match(if_rule['id'].split('|')[1]):
126 rule_is_number = True
127
128 if mac and 'mac' in if_rule and mac != if_rule['mac']:
129 sdnsh.warning('mac %s doesn\'t match mac for interface rule %s' %
130 (mac, if_rule['mac']))
131 return create_dict
132 #
133 # If the rule is a mac rule, and the associated rule is a number,
134 # make sure the 'Eth' vs 'VEth' lines up with the kind of rule
135 #
136 if ('mac' or 'ip-subnet' in if_rule or 'tags' in if_rule) and rule_is_number:
137 if not items[0].startswith('VEth'):
138 sdnsh.warning('interface name %s ought to start with VEth' %
139 items[0])
140 return create_dict
141 if ('switch' in if_rule or 'vlans' in if_rule) and rule_is_number:
142 if not items[0].startswith('Eth'):
143 sdnsh.warning('interface name %s must ought to start with Eth' %
144 items[0])
145 return create_dict
146 #
147 #
148 if ('switch' in if_rule and 'ports' in if_rule) and port:
149 if not sdnsh.switch_port_match(port, if_rule['ports']):
150 sdnsh.warning('port name %s does not match interface-rule ports %s' %
151 (port, if_rule['ports']))
152 return create_dict
153 #
154 # associate the rule_id with the interface
155 create_dict['rule'] = rule_id
156 return create_dict
157
158
159#
160# --------------------------------------------------------------------------------
161
162def port_ntoa(op, port):
163 """
164 Pass in the op and the port number, and return a string for the pair,
165 Both parameters are strings. (note the leading space)
166 """
167 if not op in ['eq', 'neq']:
168 return ''
169 return '%s %s ' % (op, port)
170
171
172#
173# --------------------------------------------------------------------------------
174
175def vns_acl_entry_to_text(acl):
176 """
177 Return a short string for a specific acl entry. Used for both short acl display
178 formats (vns-access-list-entry within a vns subconfig mode), and for show running config
179 """
180 if acl['type'] in ['tcp', 'udp']:
181 if not acl.get('src-ip') or not acl.get('src-ip-mask'):
182 return '[broken src ip or mask (a) ]'
183 if not acl.get('dst-ip') or not acl.get('dst-ip-mask'):
184 return '[broken src ip or mask (b) ]'
185 return "%s%s%s%s" % (utif.ip_and_neg_mask(acl['src-ip'],
186 acl['src-ip-mask']),
187 port_ntoa(acl.get('src-tp-port-op', ''),
188 acl.get('src-tp-port', '')),
189 utif.ip_and_neg_mask(acl['dst-ip'],
190 acl['dst-ip-mask']),
191 port_ntoa(acl.get('dst-tp-port-op', ''),
192 acl.get('dst-tp-port', '')))
193 elif acl['type'] == 'ip' or DIGITS_RE.match(acl['type']):
194 if not acl.get('src-ip') or not acl.get('src-ip-mask'):
195 return '[broken src ip or mask (c)]'
196 if not acl.get('dst-ip') or not acl.get('dst-ip-mask'):
197 return '[broken src ip or mask (d)]'
198 return "%s%s" % (utif.ip_and_neg_mask(acl['src-ip'],
199 acl['src-ip-mask']),
200 utif.ip_and_neg_mask(acl['dst-ip'],
201 acl['dst-ip-mask']))
202 elif acl['type'] == 'icmp':
203 if not acl.get('src-ip') or not acl.get('src-ip-mask'):
204 return '[broken src ip or mask (e)]'
205 if not acl.get('dst-ip') or not acl.get('dst-ip-mask'):
206 return '[broken src ip or mask (f)]'
207 return "%s%s%s" % (utif.ip_and_neg_mask(acl['src-ip'],
208 acl['src-ip-mask']),
209 utif.ip_and_neg_mask(acl['dst-ip'],
210 acl['dst-ip-mask']),
211 acl.get('icmp-type', ""))
212 elif acl['type'] == 'mac':
213 if 'vlan' in acl and acl['vlan'] != None and acl['vlan'] != '':
214 if 'ether-type' in acl and\
215 acl['ether-type'] != None and acl['ether-type'] != '':
216 return "%s %s %s vlan %s" % (acl.get('src-mac', 'any'),
217 acl.get('dst-mac', 'any'),
218 acl.get('ether-type'),
219 acl['vlan'])
220 else:
221 return "%s %s vlan %s" % (acl.get('src-mac', 'any'),
222 acl.get('dst-mac', 'any'),
223 acl['vlan'])
224 else:
225 return "%s %s %s" % (acl.get('src-mac', 'any'),
226 acl.get('dst-mac', 'any'),
227 acl.get('ether-type', ''))
228 else:
229 return '[unrecognized acl format]'
230
231
232#
233# --------------------------------------------------------------------------------
234
235def vns_acl_entries_to_brief(entries):
236 for acl in entries:
237 acl['acl-text'] = vns_acl_entry_to_text(acl)
238
239