| /* |
| * Copyright 2022-present Open Networking Foundation |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package util |
| |
| import ( |
| "encoding/binary" |
| "net" |
| "strconv" |
| "strings" |
| |
| "voltha-go-controller/internal/pkg/of" |
| ) |
| |
| // RemoveFromSlice to remove particular value from given slice. |
| func RemoveFromSlice(s []string, value string) []string { |
| i := 0 |
| for i = 0; i < len(s); i++ { |
| if s[i] == value { |
| break |
| } |
| } |
| if i != len(s) { |
| //It means value is found in the slice |
| s[len(s)-1], s[i] = s[i], s[len(s)-1] |
| return s[:len(s)-1] |
| } |
| return s |
| } |
| |
| // IsSliceSame - check and return true if the two slices are identical |
| func IsSliceSame(ref, rcvd []uint32) bool { |
| var found bool |
| if len(ref) != len(rcvd) { |
| return false |
| } |
| |
| for _, refEntry := range ref { |
| found = false |
| |
| for _, rcvdEntry := range rcvd { |
| if refEntry == rcvdEntry { |
| found = true |
| break |
| } |
| } |
| if !found { |
| return false |
| } |
| } |
| return true |
| } |
| |
| // IsPbitSliceSame - check and return true if the two slices are identical |
| func IsPbitSliceSame(ref, rcvd []of.PbitType) bool { |
| var found bool |
| if len(ref) != len(rcvd) { |
| return false |
| } |
| |
| for _, refEntry := range ref { |
| found = false |
| |
| for _, rcvdEntry := range rcvd { |
| if refEntry == rcvdEntry { |
| found = true |
| break |
| } |
| } |
| if !found { |
| return false |
| } |
| } |
| return true |
| } |
| |
| // IsNniPort is to check if given port is Nni Port. |
| func IsNniPort(id uint32) bool { |
| return (id >= 0x1000000) |
| } |
| |
| // Uint32ToByte to convert uint32 to byte |
| func Uint32ToByte(value uint32) []byte { |
| byteValue := make([]byte, 4) |
| binary.BigEndian.PutUint32(byteValue[0:4], value) |
| return byteValue |
| } |
| |
| // IP2LongConv convert ip address to integer value. |
| func IP2LongConv(ip net.IP) uint32 { |
| if len(ip) == 16 { |
| return binary.BigEndian.Uint32(ip[12:16]) |
| } |
| return binary.BigEndian.Uint32(ip) |
| } |
| |
| // Long2ipConv convert integer to ip address. |
| func Long2ipConv(nn uint32) net.IP { |
| ip := make(net.IP, 4) |
| binary.BigEndian.PutUint32(ip, nn) |
| return ip |
| } |
| |
| // GetExpIPList converts list or range of IPs to expanded IP list |
| func GetExpIPList(ips []string) []net.IP { |
| ipList := []net.IP{} |
| |
| for _, ipOrRange := range ips { |
| if strings.Contains(ipOrRange, "-") { |
| var splits = strings.Split(ipOrRange, "-") |
| ipStart := IP2LongConv(net.ParseIP(splits[0])) |
| ipEnd := IP2LongConv(net.ParseIP(splits[1])) |
| |
| for i := ipStart; i <= ipEnd; i++ { |
| ipList = append(ipList, Long2ipConv(i)) |
| } |
| } else { |
| ipList = append(ipList, net.ParseIP(ipOrRange)) |
| } |
| } |
| return ipList |
| } |
| |
| // GetUniFromMetadata returns uni port from write metadata of DS flows. |
| func GetUniFromMetadata(metadata uint64) uint32 { |
| return uint32(metadata & 0xFFFFFFFF) |
| } |
| |
| // GetUniFromDSDhcpFlow returns uni port from the flow cookie |
| func GetUniFromDSDhcpFlow(cookie uint64) uint32 { |
| uniport := uint32(cookie >> 16) |
| uniport = uniport & 0xFFFFFFFF |
| return uniport |
| } |
| |
| // GetUniPortFromFlow returns uni port from the flow data |
| func GetUniPortFromFlow(nniPort string, flow *of.VoltSubFlow) uint32 { |
| var portNo uint32 |
| if nniPort == strconv.Itoa(int(flow.Match.InPort)) { |
| if of.IPProtocolUDP == flow.Match.L4Protocol { |
| // For DHCP DS flow, uniport is not part of metadata. Hence retrieve it from cookie |
| portNo = GetUniFromDSDhcpFlow(flow.Cookie) |
| } else { |
| portNo = GetUniFromMetadata(flow.Action.Metadata) |
| } |
| } else { |
| portNo = flow.Match.InPort |
| } |
| return portNo |
| } |
| |
| // MacAddrsMatch for comparison of MAC addresses and return true if MAC addresses matches |
| func MacAddrsMatch(addr1 net.HardwareAddr, addr2 net.HardwareAddr) bool { |
| if len(addr1) != len(addr2) { |
| return false |
| } |
| for i := 0; i < len(addr1); i++ { |
| if addr1[i] != addr2[i] { |
| return false |
| } |
| } |
| return true |
| } |