blob: c0666d9056f16dd69f550044f654a304e04b18f1 [file] [log] [blame]
Naveen Sampath04696f72022-06-13 15:19:14 +05301/*
2* Copyright 2022-present Open Networking Foundation
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
vinokuma926cb3e2023-03-29 11:41:06 +053014 */
Naveen Sampath04696f72022-06-13 15:19:14 +053015
16package of
17
18import (
19 "context"
20 "net"
21 "strconv"
22
23 "github.com/google/gopacket/layers"
24
Tinoj Joseph1d108322022-07-13 10:07:39 +053025 "voltha-go-controller/log"
vinokuma926cb3e2023-03-29 11:41:06 +053026
27 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
Naveen Sampath04696f72022-06-13 15:19:14 +053028 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
29 //"github.com/opencord/voltha-protos/v5/go/voltha"
30)
31
32// PbitType type
33type PbitType uint16
34
35// TODO: Port related constants - OF specifies a different value
36// for controller. Need to make sure this is correct
37const (
38 ControllerPort uint32 = 0xfffffffd
39 PbitMatchNone PbitType = 8
40 PbitMatchAll PbitType = 0xFF
41)
42
43var logger log.CLogger
Naveen Sampath04696f72022-06-13 15:19:14 +053044var ctx = context.TODO()
45
46// ----------------------------------------------------------
47// Cookie related specifications and utilities
48// ----------------------------------------------------------
49// Though the openflow does not utilize cookies as unique identities of
50// flows, we use cookies as identities in the application. The same
51// may also be used in the VOLTHA if so desired to reduce the complexity
52// of management of flows. In terms of how the cookie is set and is
53// ensured to be unique is:
54// Cookie is a 64 bit value. The first 32 bits are set to the port-id
55// All rules set at the device level are associated with NNI. All other
56// flows, both ingress and egress are associated with the access port.
57// The last 32 bits are used to uniquely identifies flows of a port.
58const (
59 // The flow masks are used to set the MSB of the lower
60 // 32 bits of cookie
61
62 // UsFlowMask constant
63 UsFlowMask uint64 = 0x8000
64 // DsFlowMask constant
65 DsFlowMask uint64 = 0x0000
66
67 // Flow types used to divide the available cookie value range
68 // Each type is allocated 256 flow identities which are plenty
69 // for the known use cases.
70
71 // DhcpArpFlowMask constant
72 DhcpArpFlowMask uint64 = 0x0100
73 // PppoeFlowMask constant
74 PppoeFlowMask uint64 = 0x0100
75 // HsiaFlowMask constant
76 HsiaFlowMask uint64 = 0x0200
77 // DsArpFlowMask constant
78 DsArpFlowMask uint64 = 0x0300
79 // IgmpFlowMask constant
80 IgmpFlowMask uint64 = 0x0400
81 // Dhcpv6FlowMask constant
82 Dhcpv6FlowMask uint64 = 0x0800
83
84 // Flow priorities - Higher the value, higher the priority
85
86 // DhcpFlowPriority constant
87 DhcpFlowPriority uint32 = 5000
88 // ArpFlowPriority constant
89 ArpFlowPriority uint32 = 5000
90 // IgmpFlowPriority constant
91 IgmpFlowPriority uint32 = 5000
92 // McFlowPriority constant
93 McFlowPriority uint32 = 5000
94 // PppoeFlowPriority constant
95 PppoeFlowPriority uint32 = 5000
96 // HsiaFlowPriority constant
97 HsiaFlowPriority uint32 = 100
98)
99
100// CookieSetPort to set port
101func CookieSetPort(cookie uint64, port uint32) uint64 {
102 return cookie | (uint64(port) << 32)
103}
104
105// CookieGetPort to get port
106func CookieGetPort(cookie uint64) uint32 {
107 return uint32(cookie >> 32)
108}
109
110// -------------------------------------------------------
111// The flow match and action related definitions follow
112// -------------------------------------------------------
113// The Ethernet types listed below serve our requirement. We may extend
114// the list as we identify more use cases to be supported.
115
116// EtherType type
117type EtherType uint16
118
119const (
120 // EtherTypeAny constant
121 EtherTypeAny EtherType = 0x0000 // Needs assertion
122 // EtherTypeIpv4 constant
123 EtherTypeIpv4 EtherType = 0x0800
124 // EtherTypeIpv6 constant
125 EtherTypeIpv6 EtherType = 0x86DD
126 // EtherTypePppoeDiscovery constant
127 EtherTypePppoeDiscovery EtherType = 0x8863
128 // EtherTypePppoeSession constant
129 EtherTypePppoeSession EtherType = 0x8864
130 // EtherTypeArp constant
131 EtherTypeArp EtherType = 0x0806
132)
133
134// VLAN related definitions
135// VLANs can take a value between 1 and 4095. VLAN 0 is used to set just
136// the PCP bytes. VLAN 4097 is being used to represent "no VLAN"
137// 4096 is being used to represent "any vlan"
138
139// VlanType type
140type VlanType uint16
141
142const (
143 // VlanAny constant
144 VlanAny VlanType = 0x1000
145 // VlanNone constant
146 VlanNone VlanType = 0x1001
147)
148
149func (vlan *VlanType) String() string {
150 return strconv.Itoa(int(*vlan))
151}
152
153// IP Protocol defintions
154// IP protocol 0xff is reserved and we are using the reserved value to
155// represent that match is not needed.
156
157// IPProtocol type
158type IPProtocol uint8
159
160const (
161 // IPProtocolIgnore constant
162 IPProtocolIgnore IPProtocol = 0xff
163 // IPProtocolTCP constant
164 IPProtocolTCP IPProtocol = 0x06
165 // IPProtocolUDP constant
166 IPProtocolUDP IPProtocol = 0x11
167 // IPProtocolIgmp constant
168 IPProtocolIgmp IPProtocol = 0x02
169 // IPProtocolIcmpv6 constant
170 IPProtocolIcmpv6 IPProtocol = 0x3A
171)
172
173// The following structure is included in each flow which further is
174// used to create a flow. The match structure is used to specify the
175// match rules encoded into the flow.
176
177// Match structure
178type Match struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530179 SrcMacAddr net.HardwareAddr
180 SrcMacMask net.HardwareAddr
Naveen Sampath04696f72022-06-13 15:19:14 +0530181 DstMacAddr net.HardwareAddr
182 DstMacMask net.HardwareAddr
vinokuma926cb3e2023-03-29 11:41:06 +0530183 SrcIpv4Addr net.IP
184 DstIpv4Addr net.IP
185 TableMetadata uint64
186 InPort uint32
187 MatchVlan VlanType
Naveen Sampath04696f72022-06-13 15:19:14 +0530188 Pbits PbitType
189 L3Protocol EtherType
Naveen Sampath04696f72022-06-13 15:19:14 +0530190 SrcPort uint16
191 DstPort uint16
vinokuma926cb3e2023-03-29 11:41:06 +0530192 L4Protocol IPProtocol
193 DstIpv4Match bool
194 SrcIpv4Match bool
195 SrcMacMatch bool
196 DstMacMatch bool
197 MatchPbits bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530198}
199
200// Reset to be used when a Match is created. It sets the values to
201// defaults which results is no match rules at all and thus when
202// applied on a port, match all packets. The match rules must be
203// set before use.
204func (m *Match) Reset() {
205 m.MatchVlan = VlanNone
206 m.SrcMacMatch = false
207 m.DstMacMatch = false
208 m.MatchPbits = false
209 m.L3Protocol = EtherTypeAny
210 m.L4Protocol = IPProtocolIgnore
211 m.SrcPort = 0
212 m.DstPort = 0
213 m.TableMetadata = 0
214}
215
216// SetInPort to set in port
217func (m *Match) SetInPort(port uint32) {
218 m.InPort = port
219}
220
221// SetMatchVlan to set match vlan
222func (m *Match) SetMatchVlan(vlan VlanType) {
223 m.MatchVlan = vlan
224}
225
226// SetPppoeDiscoveryMatch to set L3 protocol
227func (m *Match) SetPppoeDiscoveryMatch() {
228 m.L3Protocol = EtherTypePppoeDiscovery
229}
230
231// SetTableMetadata to set table metadata
232func (m *Match) SetTableMetadata(metadata uint64) {
233 m.TableMetadata = metadata
234}
235
236// SetMatchSrcMac to set source mac address
237func (m *Match) SetMatchSrcMac(mac net.HardwareAddr) {
238 m.SrcMacMatch = true
239 m.SrcMacAddr = mac
240}
241
242// SetMatchDstMac to set destination mac address
243func (m *Match) SetMatchDstMac(mac net.HardwareAddr) {
244 m.DstMacMatch = true
245 m.DstMacAddr = mac
246}
247
248// SetMatchPbit to set pbits
249func (m *Match) SetMatchPbit(pbit PbitType) {
250 m.MatchPbits = true
251 m.Pbits = pbit
252}
253
254// SetMatchSrcIpv4 to set source ipv4 address
255func (m *Match) SetMatchSrcIpv4(ip net.IP) {
256 m.SrcIpv4Match = true
257 m.SrcIpv4Addr = ip
258}
259
260// SetMatchDstIpv4 to set destination ipv4 address
261func (m *Match) SetMatchDstIpv4(ip net.IP) {
262 m.DstIpv4Match = true
263 m.DstIpv4Addr = ip
264}
265
266// SetArpMatch to set L3 protocol as Arp
267func (m *Match) SetArpMatch() {
268 m.L3Protocol = EtherTypeArp
269}
270
271// SetICMPv6Match to set L3 and L4 protocol as IPV6 and ICMPv6
272func (m *Match) SetICMPv6Match() {
273 m.L3Protocol = EtherTypeIpv6
274 m.L4Protocol = IPProtocolIcmpv6
275}
276
277// SetUdpv4Match to set L3 and L4 protocol as IPv4 and UDP
278func (m *Match) SetUdpv4Match() {
279 m.L3Protocol = EtherTypeIpv4
280 m.L4Protocol = IPProtocolUDP
281}
282
283// SetIgmpMatch to set L3 and L4 protocol as IPv4 and Igmp
284func (m *Match) SetIgmpMatch() {
285 m.L3Protocol = EtherTypeIpv4
286 m.L4Protocol = IPProtocolIgmp
287}
288
289// SetUdpv6Match to set L3 and L4 protocol as IPv6 and UDP
290func (m *Match) SetUdpv6Match() {
291 m.L3Protocol = EtherTypeIpv6
292 m.L4Protocol = IPProtocolUDP
293}
294
295// SetIpv4Match to set L3 as IPv4
296func (m *Match) SetIpv4Match() {
297 m.L3Protocol = EtherTypeIpv4
298}
299
300// OutputType type
301type OutputType uint8
302
303const (
304 // OutputTypeDrop constant
305 OutputTypeDrop OutputType = 1
306 // OutputTypeToController constant
307 OutputTypeToController OutputType = 2
308 // OutputTypeToNetwork constant
309 OutputTypeToNetwork OutputType = 3
310 // OutputTypeGoToTable constant
311 OutputTypeGoToTable OutputType = 4
312 // OutputTypeToGroup constant
313 OutputTypeToGroup OutputType = 5
314)
315
316const (
317 // FlowAddSuccess constant
318 FlowAddSuccess = 0
319 // FlowAddFailure constant
320 FlowAddFailure = 1
321 // FlowAddPending constant
322 FlowAddPending = 2
323 // FlowDelPending constant
324 FlowDelPending = 3
325 // FlowDelFailure constant
326 FlowDelFailure = 4
327)
328
329// Action structure
330type Action struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530331 PushVlan []VlanType
vinokuma926cb3e2023-03-29 11:41:06 +0530332 Metadata uint64
Naveen Sampath04696f72022-06-13 15:19:14 +0530333 RemoveVlan int
334 OutPort uint32
335 GoToTableID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530336 MeterID uint32
vinokuma926cb3e2023-03-29 11:41:06 +0530337 EtherType layers.EthernetType
338 SetVlan VlanType
Naveen Sampath04696f72022-06-13 15:19:14 +0530339 Pcp PbitType
vinokuma926cb3e2023-03-29 11:41:06 +0530340 Output OutputType
Naveen Sampath04696f72022-06-13 15:19:14 +0530341}
342
343const (
344 // PbitNone constant
345 PbitNone PbitType = 8
346)
347
348// Reset the action structure
349func (a *Action) Reset() {
350 a.Output = OutputTypeDrop
351 a.PushVlan = make([]VlanType, 0)
352 a.SetVlan = VlanNone
353 a.RemoveVlan = 0
354 a.Metadata = 0
355 a.MeterID = 0
356 a.Pcp = PbitNone
357}
358
359// SetReportToController for set action to report to controller
360func (a *Action) SetReportToController() {
361 a.Output = OutputTypeToController
362 a.OutPort = ControllerPort
363}
364
365// SetPushVlan for set action to push to vlan
366func (a *Action) SetPushVlan(vlan VlanType, etherType layers.EthernetType) {
367 a.PushVlan = append(a.PushVlan, vlan)
368 a.EtherType = etherType
369}
370
371// SetSetVlan to set SetVlan
372func (a *Action) SetSetVlan(vlan VlanType) {
373 a.SetVlan = vlan
374}
375
376// SetPopVlan to set remove vlan counter
377func (a *Action) SetPopVlan() {
378 a.RemoveVlan++
379}
380
381// SetMeterID to set meter id
382func (a *Action) SetMeterID(meterID uint32) {
383 a.MeterID = meterID
384}
385
386// SetWriteMetadata to set metadata
387func (a *Action) SetWriteMetadata(metadata uint64) {
388 a.Metadata = metadata
389}
390
391// SetPcp to set pcp
392func (a *Action) SetPcp(pcp PbitType) {
393 a.Pcp = pcp
394}
395
396// GetWriteMetadata returns metadata
397func (a *Action) GetWriteMetadata() uint64 {
398 return a.Metadata
399}
400
401// SetOutPort to set output port
402func (a *Action) SetOutPort(port uint32) {
403 a.Output = OutputTypeToNetwork
404 a.OutPort = port
405}
406
407// SetOutGroup to set output group
408func (a *Action) SetOutGroup(group uint32) {
409 a.Output = OutputTypeToGroup
410 a.OutPort = group
411}
412
413// SetGoToTable to set GoToTableID
414func (a *Action) SetGoToTable(table uint32) {
415 a.Output = OutputTypeGoToTable
416 a.GoToTableID = table
417}
418
419// VoltSubFlow structure
420type VoltSubFlow struct {
Naveen Sampath04696f72022-06-13 15:19:14 +0530421 ErrorReason string
422 Match
423 Action
vinokuma926cb3e2023-03-29 11:41:06 +0530424 Cookie uint64
425 CookieMask uint64
426 // OldCookie is used in vgc upgrade when there is cookie generation logic change.
427 OldCookie uint64
428 TableID uint32
429 Priority uint32
430 State uint8
Akash Sonief452f12024-12-12 18:20:28 +0530431 FlowCount uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530432}
433
434// NewVoltSubFlow is constructor for VoltSubFlow
435func NewVoltSubFlow() *VoltSubFlow {
436 var sf VoltSubFlow
437 sf.Match.Reset()
438 sf.Action.Reset()
439 return &sf
440}
441
442// SetTableID to set table id
443func (sf *VoltSubFlow) SetTableID(tableID uint32) {
444 sf.TableID = tableID
445}
446
447// Command type
448type Command uint8
449
450const (
451 // CommandAdd constant
452 CommandAdd Command = 0
453 // CommandDel constant
454 CommandDel Command = 1
455)
456
457// VoltFlow : Definition of a flow
458type VoltFlow struct {
vinokuma926cb3e2023-03-29 11:41:06 +0530459 SubFlows map[uint64]*VoltSubFlow
460 // PortName and PortID to be used for validation of port before flow pushing
461 PortName string
462 PortID uint32
Naveen Sampath04696f72022-06-13 15:19:14 +0530463 Command Command
Naveen Sampath04696f72022-06-13 15:19:14 +0530464 ForceAction bool
465 MigrateCookie bool
Naveen Sampath04696f72022-06-13 15:19:14 +0530466}
467
468const (
469 // PrevBwInfo indicates the string returned by core for bandwidth consumed before creating scheduler
470 PrevBwInfo string = "prevBW"
471 // PresentBwInfo indicates the string returned by core for bandwidth consumed after creating scheduler
472 PresentBwInfo string = "presentBW"
473)
474
475// BwAvailDetails consists of bw consumtion details at olt
476type BwAvailDetails struct {
477 PrevBw string
478 PresentBw string
479}
480
481// -------------------------------------------------------------------
482// OPENFLOW Implementation of flows
483//
484// The flows constructed using the above structures is translated to
485// the VOLTHA OpenFlow GRPC structures. The code below is used to
486// construct the VOLTHA OF GRPC structures.
487const (
488 // DefaultMeterID constant
489 DefaultMeterID uint32 = 0x1
490 // DefaultBufferID constant
491 DefaultBufferID uint32 = 0xffffffff
492 // DefaultOutPort constant
493 DefaultOutPort uint32 = 0xffffffff
494 // DefaultOutGroup constant
495 DefaultOutGroup uint32 = 0xffffffff
496 // DefaultFlags constant
497 DefaultFlags uint32 = 0x1
498)
499
500// NewInportMatch for inport info
501func NewInportMatch(port uint32) *ofp.OfpOxmField {
502 var entry ofp.OfpOxmField
503 var mf ofp.OfpOxmOfbField
504 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
505 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
506 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT
507 mf.HasMask = false
508 mf.Value = &ofp.OfpOxmOfbField_Port{Port: port}
509 return &entry
510}
511
512// NewTableMetadataMatch for table metadata
513func NewTableMetadataMatch(metadata uint64) *ofp.OfpOxmField {
514 var entry ofp.OfpOxmField
515 var mf ofp.OfpOxmOfbField
516 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
517 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
518 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_METADATA
519 mf.HasMask = false
520 mf.Value = &ofp.OfpOxmOfbField_TableMetadata{TableMetadata: metadata}
521 return &entry
522}
523
524// NewSrcMacAddrMatch for source mac address info
525func NewSrcMacAddrMatch(addr []byte) *ofp.OfpOxmField {
526 var entry ofp.OfpOxmField
527 var mf ofp.OfpOxmOfbField
528 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
529 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
530 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_SRC
531 mf.HasMask = false
532 mf.Value = &ofp.OfpOxmOfbField_EthSrc{EthSrc: addr}
533 return &entry
534}
535
536// NewDstMacAddrMatch for destination mac address info
537func NewDstMacAddrMatch(addr []byte) *ofp.OfpOxmField {
538 var entry ofp.OfpOxmField
539 var mf ofp.OfpOxmOfbField
540 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
541 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
542 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_DST
543 mf.HasMask = false
544 mf.Value = &ofp.OfpOxmOfbField_EthDst{EthDst: addr}
545 return &entry
546}
547
548// NewVlanMatch for vlan info
549func NewVlanMatch(vlan uint16) *ofp.OfpOxmField {
550 var entry ofp.OfpOxmField
551 var mf ofp.OfpOxmOfbField
552 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
553 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
554 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID
555 mf.HasMask = false
556 mf.Value = &ofp.OfpOxmOfbField_VlanVid{VlanVid: uint32(vlan&0x0fff + 0x1000)}
557 mf.Mask = &ofp.OfpOxmOfbField_VlanVidMask{VlanVidMask: uint32(0x1000)}
558 return &entry
559}
560
561// NewPcpMatch for pcp info
562func NewPcpMatch(pbits PbitType) *ofp.OfpOxmField {
563 var entry ofp.OfpOxmField
564 var mf ofp.OfpOxmOfbField
565 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
566 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
567 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP
568 mf.HasMask = false
569 mf.Value = &ofp.OfpOxmOfbField_VlanPcp{VlanPcp: uint32(pbits)}
570 return &entry
571}
572
573// NewEthTypeMatch for eth type info
574func NewEthTypeMatch(l3proto uint16) *ofp.OfpOxmField {
575 var entry ofp.OfpOxmField
576 var mf ofp.OfpOxmOfbField
577 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
578 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
579 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE
580 mf.HasMask = false
581 mf.Value = &ofp.OfpOxmOfbField_EthType{EthType: uint32(l3proto)}
582 return &entry
583}
584
585// ipv4ToUint to convert ipv4 to uint
586func ipv4ToUint(ip net.IP) uint32 {
587 result := uint32(0)
588 addr := ip.To4()
589 if addr == nil {
590 logger.Warnw(ctx, "Invalid Group Addr", log.Fields{"IP": ip})
591 return 0
592 }
593 result = result + uint32(addr[0])<<24
594 result = result + uint32(addr[1])<<16
595 result = result + uint32(addr[2])<<8
596 result = result + uint32(addr[3])
597 return result
598}
599
600// NewIpv4SrcMatch for ipv4 source address
601func NewIpv4SrcMatch(ip net.IP) *ofp.OfpOxmField {
602 var entry ofp.OfpOxmField
603 var mf ofp.OfpOxmOfbField
604 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
605 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
606 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_SRC
607 mf.HasMask = false
608 mf.Value = &ofp.OfpOxmOfbField_Ipv4Src{Ipv4Src: ipv4ToUint(ip)}
609 return &entry
610}
611
612// NewIpv4DstMatch for ipv4 destination address
613func NewIpv4DstMatch(ip net.IP) *ofp.OfpOxmField {
614 var entry ofp.OfpOxmField
615 var mf ofp.OfpOxmOfbField
616 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
617 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
618 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST
619 mf.HasMask = false
620 mf.Value = &ofp.OfpOxmOfbField_Ipv4Dst{Ipv4Dst: ipv4ToUint(ip)}
621 return &entry
622}
623
624// NewIPProtoMatch for ip proto info
625func NewIPProtoMatch(l4proto uint16) *ofp.OfpOxmField {
626 var entry ofp.OfpOxmField
627 var mf ofp.OfpOxmOfbField
628 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
629 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
630 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO
631 mf.HasMask = false
632 mf.Value = &ofp.OfpOxmOfbField_IpProto{IpProto: uint32(l4proto)}
633 return &entry
634}
635
636// NewUDPSrcMatch for source udp info
637func NewUDPSrcMatch(port uint16) *ofp.OfpOxmField {
638 var entry ofp.OfpOxmField
639 var mf ofp.OfpOxmOfbField
640 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
641 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
642 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC
643 mf.HasMask = false
644 mf.Value = &ofp.OfpOxmOfbField_UdpSrc{UdpSrc: uint32(port)}
645 return &entry
646}
647
648// NewUDPDstMatch for destination udp info
649func NewUDPDstMatch(port uint16) *ofp.OfpOxmField {
650 var entry ofp.OfpOxmField
651 var mf ofp.OfpOxmOfbField
652 entry.OxmClass = ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC
653 entry.Field = &ofp.OfpOxmField_OfbField{OfbField: &mf}
654 mf.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST
655 mf.HasMask = false
656 mf.Value = &ofp.OfpOxmOfbField_UdpDst{UdpDst: uint32(port)}
657 return &entry
658}
659
660// NewMeterIDInstruction for meter id instructions
661func NewMeterIDInstruction(meterID uint32) *ofp.OfpInstruction {
662 var meter ofp.OfpInstruction
663 meter.Type = uint32(ofp.OfpInstructionType_OFPIT_METER)
664 meter.Data = &ofp.OfpInstruction_Meter{
665 Meter: &ofp.OfpInstructionMeter{
666 MeterId: meterID,
667 },
668 }
669 return &meter
670}
671
672// NewGoToTableInstruction for go to table instructions
673func NewGoToTableInstruction(table uint32) *ofp.OfpInstruction {
674 var gotoTable ofp.OfpInstruction
675 gotoTable.Type = uint32(ofp.OfpInstructionType_OFPIT_GOTO_TABLE)
676 gotoTable.Data = &ofp.OfpInstruction_GotoTable{
677 GotoTable: &ofp.OfpInstructionGotoTable{
678 TableId: table,
679 },
680 }
681 return &gotoTable
682}
683
684// NewPopVlanInstruction for pop vlan instructions
685func NewPopVlanInstruction() *ofp.OfpInstruction {
686 var removeTag ofp.OfpInstruction
687 var actions ofp.OfpInstructionActions
688 removeTag.Type = uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS)
689 removeTag.Data = &ofp.OfpInstruction_Actions{
690 Actions: &actions,
691 }
692 action := flows.PopVlan()
693 actions.Actions = append(actions.Actions, action)
694 return &removeTag
695}
696
697// NewWriteMetadataInstruction for write metadata instructions
698func NewWriteMetadataInstruction(metadata uint64) *ofp.OfpInstruction {
699 var md ofp.OfpInstruction
700 md.Type = uint32(ofp.OfpInstructionType_OFPIT_WRITE_METADATA)
701 md.Data = &ofp.OfpInstruction_WriteMetadata{WriteMetadata: &ofp.OfpInstructionWriteMetadata{Metadata: metadata}}
702 return &md
703}
704
705// NewPopVlanAction for pop vlan action
706func NewPopVlanAction() *ofp.OfpAction {
707 return flows.PopVlan()
708}
709
710// NewPushVlanInstruction for push vlan instructions
711func NewPushVlanInstruction(vlan uint16, etherType uint32) *ofp.OfpInstruction {
712 var addTag ofp.OfpInstruction
713 var actions ofp.OfpInstructionActions
714 addTag.Type = uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS)
715 addTag.Data = &ofp.OfpInstruction_Actions{
716 Actions: &actions,
717 }
718 pushAction := flows.PushVlan(etherType)
719 actions.Actions = append(actions.Actions, pushAction)
720 var setField ofp.OfpOxmOfbField
721 setField.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID
722 setField.HasMask = false
723 setField.Value = &ofp.OfpOxmOfbField_VlanVid{
724 VlanVid: uint32(vlan&0x0fff + 0x1000),
725 }
726 setAction := flows.SetField(&setField)
727 actions.Actions = append(actions.Actions, setAction)
728 return &addTag
729}
730
731// NewPushVlanAction for push vlan action
732func NewPushVlanAction(etherType uint32) *ofp.OfpAction {
733 pushAction := flows.PushVlan(etherType)
734 return pushAction
735}
736
737// NewSetVlanAction for set vlan action
738func NewSetVlanAction(vlan uint16) *ofp.OfpAction {
739 var setField ofp.OfpOxmOfbField
740 setField.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID
741 setField.HasMask = false
742 and := (vlan & 0xfff)
743 or := and + 0x1000
744 v := uint32(vlan&0x0fff + 0x1000)
Akash Sonief452f12024-12-12 18:20:28 +0530745 logger.Debugw(ctx, "Vlan Construction", log.Fields{"Vlan": vlan, "vlan&0x0fff": and, "OR": or, "final": v})
Naveen Sampath04696f72022-06-13 15:19:14 +0530746 setField.Value = &ofp.OfpOxmOfbField_VlanVid{
747 VlanVid: uint32(vlan&0x0fff + 0x1000),
748 }
749 setAction := flows.SetField(&setField)
750 return setAction
751}
752
753// NewSetPcpAction for set pcap action
754func NewSetPcpAction(pbits PbitType) *ofp.OfpAction {
755 var setField ofp.OfpOxmOfbField
756 setField.Type = ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP
757 setField.HasMask = false
758 setField.Value = &ofp.OfpOxmOfbField_VlanPcp{VlanPcp: uint32(pbits)}
759 setAction := flows.SetField(&setField)
760 return setAction
761}
762
763// NewOutputInstruction for output instructions
764func NewOutputInstruction(port uint32) *ofp.OfpInstruction {
765 var outport ofp.OfpInstruction
766 var actions ofp.OfpInstructionActions
767 outport.Type = uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS)
768 outport.Data = &ofp.OfpInstruction_Actions{
769 Actions: &actions,
770 }
771 action := flows.Output(port, 65535)
772 actions.Actions = append(actions.Actions, action)
773 return &outport
774}
775
776// NewOutputAction for output action
777func NewOutputAction(port uint32) *ofp.OfpAction {
778 return flows.Output(port, 65535)
779}
780
781// NewGroupOutputInstruction for group output instructions
782func NewGroupOutputInstruction(group uint32) *ofp.OfpInstruction {
783 var outgroup ofp.OfpInstruction
784 var actions ofp.OfpInstructionActions
785 outgroup.Type = uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS)
786 outgroup.Data = &ofp.OfpInstruction_Actions{
787 Actions: &actions,
788 }
789 action := flows.Group(group)
790 actions.Actions = append(actions.Actions, action)
791 return &outgroup
792}
793
794// NewGroupAction for group action
795func NewGroupAction(group uint32) *ofp.OfpAction {
796 return flows.Group(group)
797}
798
799// CreateMatchAndActions to create match list and action
800func CreateMatchAndActions(f *VoltSubFlow) ([]*ofp.OfpOxmField, []*ofp.OfpInstruction) {
801 logger.Debug(ctx, "Create Match and Action called")
802
803 // Return values declared here
804 var matchList []*ofp.OfpOxmField
805 var instructions []*ofp.OfpInstruction
806
807 // Construct the match rules
808 // Add match in port
809 if f.Match.InPort != 0 {
810 entry := NewInportMatch(uint32(f.Match.InPort))
811 matchList = append(matchList, entry)
812 }
813
814 // Add table metadata match
815 if f.Match.TableMetadata != 0 {
816 entry := NewTableMetadataMatch(uint64(f.Match.TableMetadata))
817 matchList = append(matchList, entry)
818 }
819
820 // Add Src MAC address match
821 if f.SrcMacMatch {
822 entry := NewSrcMacAddrMatch(f.SrcMacAddr)
823 matchList = append(matchList, entry)
824 }
825
826 // Add Src MAC address match
827 if f.DstMacMatch {
828 entry := NewDstMacAddrMatch(f.DstMacAddr)
829 matchList = append(matchList, entry)
830 }
831
832 // Add VLAN tag match
833 if f.MatchVlan != VlanNone {
834 entry := NewVlanMatch(uint16(f.MatchVlan))
835 matchList = append(matchList, entry)
836 }
837
838 if f.MatchPbits {
839 entry := NewPcpMatch(f.Pbits)
840 matchList = append(matchList, entry)
841 }
842
843 // Add EtherType match
844 if f.L3Protocol != EtherTypeAny {
845 entry := NewEthTypeMatch(uint16(f.L3Protocol))
846 matchList = append(matchList, entry)
847 }
848
849 // Add the Src IPv4 addr match
850 if f.SrcIpv4Match {
851 entry := NewIpv4SrcMatch(f.SrcIpv4Addr)
852 matchList = append(matchList, entry)
853 }
854
855 // Add the Dst IPv4 addr match
856 if f.DstIpv4Match {
857 entry := NewIpv4DstMatch(f.DstIpv4Addr)
858 matchList = append(matchList, entry)
859 }
860
861 // Add IP protocol match
862 if f.L4Protocol != IPProtocolIgnore {
863 entry := NewIPProtoMatch(uint16(f.L4Protocol))
864 matchList = append(matchList, entry)
865 }
866
867 // Add UDP Source port match
868 if f.SrcPort != 0 {
869 entry := NewUDPSrcMatch(uint16(f.SrcPort))
870 matchList = append(matchList, entry)
871 }
872
873 // Add UDP Dest port match
874 if f.DstPort != 0 {
875 entry := NewUDPDstMatch(uint16(f.DstPort))
876 matchList = append(matchList, entry)
877 }
878
879 // Construct the instructions
880 // Add a GOTO table action
881 if f.Output == OutputTypeGoToTable {
882 instruction := NewGoToTableInstruction(f.GoToTableID)
883 instructions = append(instructions, instruction)
884 }
885
886 // Add the meter instruction
887 if f.MeterID != 0 {
888 instruction := NewMeterIDInstruction(f.MeterID)
889 instructions = append(instructions, instruction)
890 }
891
892 // Add the metadata instruction
893 if f.Metadata != 0 {
894 instruction := NewWriteMetadataInstruction(f.Metadata)
895 instructions = append(instructions, instruction)
896 }
897
898 // The below are all apply actions. All of these could be combined into
899 // a single instruction.
900 {
901 var instruction ofp.OfpInstruction
902 var actions ofp.OfpInstructionActions
903 instruction.Type = uint32(ofp.OfpInstructionType_OFPIT_APPLY_ACTIONS)
904 instruction.Data = &ofp.OfpInstruction_Actions{
905 Actions: &actions,
906 }
907
908 // Apply action of popping the VLAN
909 if f.RemoveVlan != 0 {
910 for i := 0; i < f.RemoveVlan; i++ {
911 action := NewPopVlanAction()
912 actions.Actions = append(actions.Actions, action)
913 }
914 }
915
916 if f.SetVlan != VlanNone {
917 action := NewSetVlanAction(uint16(f.SetVlan))
918 actions.Actions = append(actions.Actions, action)
919 }
920
921 if f.Pcp != PbitNone {
922 action := NewSetPcpAction(f.Pcp)
923 actions.Actions = append(actions.Actions, action)
924 }
925
926 // Add the VLAN PUSH
927 if len(f.PushVlan) != 0 {
928 action := NewPushVlanAction(uint32(f.EtherType))
929 actions.Actions = append(actions.Actions, action)
930 for _, vlan := range f.PushVlan {
931 action = NewSetVlanAction(uint16(vlan))
932 actions.Actions = append(actions.Actions, action)
933 }
934 }
935
936 if f.Action.Output == OutputTypeToController {
937 action := NewOutputAction(0xfffffffd)
938 actions.Actions = append(actions.Actions, action)
939 } else if f.Action.Output == OutputTypeToNetwork {
940 action := NewOutputAction(f.OutPort)
941 actions.Actions = append(actions.Actions, action)
942 } else if f.Action.Output == OutputTypeToGroup {
943 action := NewGroupAction(f.OutPort)
944 actions.Actions = append(actions.Actions, action)
945 }
946 instructions = append(instructions, &instruction)
947 }
948
949 return matchList, instructions
950}
951
952// CreateFlow to create flow
953func CreateFlow(device string, command ofp.OfpFlowModCommand, matches []*ofp.OfpOxmField,
954 instructions []*ofp.OfpInstruction, sf *VoltSubFlow) *ofp.FlowTableUpdate {
955 flowUpdate := ofp.FlowTableUpdate{
956 Id: device,
957 FlowMod: &ofp.OfpFlowMod{
958 Cookie: sf.Cookie,
959 CookieMask: sf.CookieMask,
960 TableId: sf.TableID,
961 Command: command,
962 IdleTimeout: uint32(0),
963 HardTimeout: uint32(0),
964 Priority: sf.Priority,
965 BufferId: DefaultBufferID,
966 OutPort: DefaultOutPort,
967 OutGroup: DefaultOutGroup,
968 Flags: DefaultFlags,
969 Match: &ofp.OfpMatch{
970 Type: ofp.OfpMatchType_OFPMT_OXM,
971 OxmFields: matches,
972 },
973
974 Instructions: instructions,
975 },
976 }
977 return &flowUpdate
978}
979
980// Processing logic for the VOLT flows. The VOLT flows are different from
981// the normal openflows. Each VOLT flow may break into multiple flows.
982// The order of processing:
983// 1. If the flow has to match more than one VLAN tag, it is broken into
984// more than one flow.
985// 2. When more than one flow is creatd, the higher layer processing is
986// broken into the second flow. The first flow includes only the
987// the processing of first VLAN tag.
988// 3. The a sinle flow is created, the first flow has all the match criteria
989// and action.
990
991// ProcessVoltFlow to process volt flow
992func ProcessVoltFlow(device string, operation Command, subFlow map[uint64]*VoltSubFlow) []*ofp.FlowTableUpdate {
993 var flows []*ofp.FlowTableUpdate
994 var command ofp.OfpFlowModCommand
995 if operation == CommandAdd {
996 command = ofp.OfpFlowModCommand_OFPFC_ADD
997 } else {
998 command = ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT
999 }
1000 for _, sf := range subFlow {
1001 logger.Debugw(ctx, "Flow Construction for", log.Fields{"Flow": sf})
1002 match, instruction := CreateMatchAndActions(sf)
1003 flow := CreateFlow(device, command, match, instruction, sf)
1004 logger.Debugw(ctx, "Flow Constructed", log.Fields{"Flow": flow})
1005 flows = append(flows, flow)
1006 }
1007 return flows
1008}
1009
1010func init() {
1011 // Setup this package so that it's log level can be modified at run time
1012 var err error
Tinoj Joseph1d108322022-07-13 10:07:39 +05301013 logger, err = log.AddPackageWithDefaultParam()
Naveen Sampath04696f72022-06-13 15:19:14 +05301014 if err != nil {
1015 panic(err)
1016 }
1017}