This repository has been archived by the owner on Aug 3, 2020. It is now read-only.
forked from ligato/vpp-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
abf_vppcalls.go
188 lines (164 loc) · 6.2 KB
/
abf_vppcalls.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright (c) 2019 Cisco and/or its affiliates.
//
// 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 vpp2001
import (
"fmt"
"net"
"github.com/go-errors/errors"
abf "github.com/ligato/vpp-agent/api/models/vpp/abf"
vpp_abf "github.com/ligato/vpp-agent/plugins/vpp/binapi/vpp2001/abf"
)
const (
// NextHopViaLabelUnset constant has to be assigned into the field next hop via label
// in abf_policy_add_del binary message if next hop via label is not defined.
NextHopViaLabelUnset uint32 = 0xfffff + 1
// ClassifyTableIndexUnset is a default value for field classify_table_index
// in abf_policy_add_del binary message.
ClassifyTableIndexUnset = ^uint32(0)
)
// GetAbfVersion retrieves version of the VPP ABF plugin
func (h *ABFVppHandler) GetAbfVersion() (ver string, err error) {
req := &vpp_abf.AbfPluginGetVersion{}
reply := &vpp_abf.AbfPluginGetVersionReply{}
if err := h.callsChannel.SendRequest(req).ReceiveReply(reply); err != nil {
return "", err
}
return fmt.Sprintf("%d.%d", reply.Major, reply.Minor), nil
}
// AddAbfPolicy creates new ABF entry together with a list of forwarding paths
func (h *ABFVppHandler) AddAbfPolicy(policyID, aclID uint32, abfPaths []*abf.ABF_ForwardingPath) error {
if err := h.abfAddDelPolicy(policyID, aclID, abfPaths, true); err != nil {
return errors.Errorf("failed to add ABF policy %d (ACL: %v): %v", policyID, aclID, err)
}
return nil
}
// DeleteAbfPolicy removes existing ABF entry
func (h *ABFVppHandler) DeleteAbfPolicy(policyID uint32, abfPaths []*abf.ABF_ForwardingPath) error {
if err := h.abfAddDelPolicy(policyID, 0, abfPaths, false); err != nil {
return errors.Errorf("failed to delete ABF policy %d: %v", policyID, err)
}
return nil
}
// AbfAttachInterfaceIPv4 attaches IPv4 interface to the ABF
func (h *ABFVppHandler) AbfAttachInterfaceIPv4(policyID, ifIdx, priority uint32) error {
if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, true, false); err != nil {
return errors.Errorf("failed to attach IPv4 interface %d to ABF policy %d: %v", ifIdx, policyID, err)
}
return nil
}
// AbfDetachInterfaceIPv4 detaches IPV4 interface from the ABF
func (h *ABFVppHandler) AbfDetachInterfaceIPv4(policyID, ifIdx, priority uint32) error {
if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, false, false); err != nil {
return errors.Errorf("failed to detach IPv4 interface %d from ABF policy %d: %v", ifIdx, policyID, err)
}
return nil
}
// AbfAttachInterfaceIPv6 attaches IPv6 interface to the ABF
func (h *ABFVppHandler) AbfAttachInterfaceIPv6(policyID, ifIdx, priority uint32) error {
if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, true, true); err != nil {
return errors.Errorf("failed to attach IPv6 interface %d to ABF policy %d: %v", ifIdx, policyID, err)
}
return nil
}
// AbfDetachInterfaceIPv6 detaches IPv6 interface from the ABF
func (h *ABFVppHandler) AbfDetachInterfaceIPv6(policyID, ifIdx, priority uint32) error {
if err := h.abfAttachDetachInterface(policyID, ifIdx, priority, false, true); err != nil {
return errors.Errorf("failed to detach IPv6 interface %d from ABF policy %d: %v", ifIdx, policyID, err)
}
return nil
}
func (h *ABFVppHandler) abfAttachDetachInterface(policyID, ifIdx, priority uint32, isAdd, isIPv6 bool) error {
req := &vpp_abf.AbfItfAttachAddDel{
IsAdd: boolToUint(isAdd),
Attach: vpp_abf.AbfItfAttach{
PolicyID: policyID,
SwIfIndex: ifIdx,
Priority: priority,
IsIPv6: boolToUint(isIPv6),
},
}
reply := &vpp_abf.AbfItfAttachAddDelReply{}
return h.callsChannel.SendRequest(req).ReceiveReply(reply)
}
func (h *ABFVppHandler) abfAddDelPolicy(policyID, aclID uint32, abfPaths []*abf.ABF_ForwardingPath, isAdd bool) error {
req := &vpp_abf.AbfPolicyAddDel{
IsAdd: boolToUint(isAdd),
Policy: vpp_abf.AbfPolicy{
PolicyID: policyID,
ACLIndex: aclID,
Paths: h.toFibPaths(abfPaths),
NPaths: uint8(len(abfPaths)),
},
}
reply := &vpp_abf.AbfPolicyAddDelReply{}
return h.callsChannel.SendRequest(req).ReceiveReply(reply)
}
func (h *ABFVppHandler) toFibPaths(abfPaths []*abf.ABF_ForwardingPath) (fibPaths []vpp_abf.FibPath) {
var err error
for _, abfPath := range abfPaths {
// fib path interface
ifData, exists := h.ifIndexes.LookupByName(abfPath.InterfaceName)
if !exists {
continue
}
fibPath := vpp_abf.FibPath{
SwIfIndex: ifData.SwIfIndex,
Weight: uint8(abfPath.Weight),
Preference: uint8(abfPath.Preference),
Type: setFibPathType(abfPath.Dvr),
}
if fibPath.Nh, fibPath.Proto, err = setFibPathNhAndProto(abfPath.NextHopIp); err != nil {
h.log.Errorf("ABF path next hop error: %v", err)
}
fibPaths = append(fibPaths, fibPath)
}
return fibPaths
}
// supported cases are DVR and normal
func setFibPathType(isDvr bool) vpp_abf.FibPathType {
if isDvr {
return vpp_abf.FIB_API_PATH_TYPE_DVR
}
return vpp_abf.FIB_API_PATH_TYPE_NORMAL
}
// resolve IP address and return FIB path next hop (IP address) and IPv4/IPv6 version
func setFibPathNhAndProto(ipStr string) (nh vpp_abf.FibPathNh, proto vpp_abf.FibPathNhProto, err error) {
netIP := net.ParseIP(ipStr)
if netIP == nil {
return nh, proto, errors.Errorf("failed to parse next hop IP address %s", ipStr)
}
var au vpp_abf.AddressUnion
if ipv4 := netIP.To4(); ipv4 == nil {
var address vpp_abf.IP6Address
proto = vpp_abf.FIB_API_PATH_NH_PROTO_IP6
copy(address[:], netIP[:])
au.SetIP6(address)
} else {
var address vpp_abf.IP4Address
proto = vpp_abf.FIB_API_PATH_NH_PROTO_IP4
copy(address[:], netIP[12:])
au.SetIP4(address)
}
return vpp_abf.FibPathNh{
Address: au,
ViaLabel: NextHopViaLabelUnset,
ClassifyTableIndex: ClassifyTableIndexUnset,
}, proto, nil
}
func boolToUint(input bool) uint8 {
if input {
return 1
}
return 0
}