pnat: add support to wildcard IP Protocol field if not specified
- add pnat_binding_add_v2 which explicitly requires match mask to set to PNAT_PROTO if we want to match on IP Protocol - fix pnat_binding_add backward compatibility i.e. no need to set match mast to PNAT_PROTO Type: improvement Signed-off-by: Fahad Naeem <fahadnaeemkhan@gmail.com> Change-Id: I5a23244be55b7d4c10552c555881527a4b2f325f
This commit is contained in:
@@ -26,6 +26,7 @@ enum pnat_mask
|
||||
PNAT_DPORT = 0x8,
|
||||
PNAT_COPY_BYTE = 0x10,
|
||||
PNAT_CLEAR_BYTE = 0x20,
|
||||
PNAT_PROTO = 0x40,
|
||||
};
|
||||
|
||||
enum pnat_attachment_point
|
||||
@@ -65,6 +66,7 @@ autoendian define pnat_binding_add
|
||||
vl_api_pnat_rewrite_tuple_t rewrite;
|
||||
};
|
||||
|
||||
|
||||
autoendian define pnat_binding_add_reply
|
||||
{
|
||||
u32 context;
|
||||
@@ -72,6 +74,22 @@ autoendian define pnat_binding_add_reply
|
||||
u32 binding_index;
|
||||
};
|
||||
|
||||
autoendian define pnat_binding_add_v2
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_pnat_match_tuple_t match;
|
||||
vl_api_pnat_rewrite_tuple_t rewrite;
|
||||
};
|
||||
|
||||
|
||||
autoendian define pnat_binding_add_v2_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u32 binding_index;
|
||||
};
|
||||
|
||||
autoendian autoreply define pnat_binding_del
|
||||
{
|
||||
u32 client_index;
|
||||
|
||||
@@ -56,7 +56,9 @@ static pnat_mask_fast_t pnat_mask2fast(pnat_mask_t lookup_mask) {
|
||||
m.as_u64[0] = 0xffffffff00000000;
|
||||
if (lookup_mask & PNAT_DA)
|
||||
m.as_u64[0] |= 0x00000000ffffffff;
|
||||
m.as_u64[1] = 0xffffffff00000000;
|
||||
m.as_u64[1] = 0x00ffffff00000000;
|
||||
if (lookup_mask & PNAT_PROTO)
|
||||
m.as_u64[1] |= 0xff00000000000000;
|
||||
if (lookup_mask & PNAT_SPORT)
|
||||
m.as_u64[1] |= 0x00000000ffff0000;
|
||||
if (lookup_mask & PNAT_DPORT)
|
||||
|
||||
@@ -36,11 +36,26 @@ static void vl_api_pnat_binding_add_t_handler(vl_api_pnat_binding_add_t *mp) {
|
||||
pnat_main_t *pm = &pnat_main;
|
||||
vl_api_pnat_binding_add_reply_t *rmp;
|
||||
u32 binding_index;
|
||||
|
||||
// for backward compatibility
|
||||
if (mp->match.proto == 0)
|
||||
mp->match.mask |= PNAT_PROTO;
|
||||
|
||||
int rv = pnat_binding_add(&mp->match, &mp->rewrite, &binding_index);
|
||||
REPLY_MACRO2_END(VL_API_PNAT_BINDING_ADD_REPLY,
|
||||
({ rmp->binding_index = binding_index; }));
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_pnat_binding_add_v2_t_handler(vl_api_pnat_binding_add_t *mp) {
|
||||
pnat_main_t *pm = &pnat_main;
|
||||
vl_api_pnat_binding_add_reply_t *rmp;
|
||||
u32 binding_index;
|
||||
int rv = pnat_binding_add(&mp->match, &mp->rewrite, &binding_index);
|
||||
REPLY_MACRO2_END(VL_API_PNAT_BINDING_ADD_V2_REPLY,
|
||||
({ rmp->binding_index = binding_index; }));
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_pnat_binding_attach_t_handler(vl_api_pnat_binding_attach_t *mp) {
|
||||
pnat_main_t *pm = &pnat_main;
|
||||
|
||||
@@ -122,6 +122,8 @@ uword unformat_pnat_match_tuple(unformat_input_t *input, va_list *args) {
|
||||
t->mask |= PNAT_SA;
|
||||
else if (unformat(input, "dst %U", unformat_ip4_address, &t->dst))
|
||||
t->mask |= PNAT_DA;
|
||||
else if (unformat(input, "proto %U", unformat_ip_protocol, &t->proto))
|
||||
t->mask |= PNAT_PROTO;
|
||||
else if (unformat(input, "sport %d", &sport)) {
|
||||
if (sport == 0 || sport > 65535)
|
||||
return 0;
|
||||
@@ -132,9 +134,7 @@ uword unformat_pnat_match_tuple(unformat_input_t *input, va_list *args) {
|
||||
return 0;
|
||||
t->mask |= PNAT_DPORT;
|
||||
t->dport = dport;
|
||||
} else if (unformat(input, "proto %U", unformat_ip_protocol, &t->proto))
|
||||
;
|
||||
else
|
||||
} else
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -242,6 +242,105 @@ class TestPNAT(VppTestCase):
|
||||
)
|
||||
self.vapi.pnat_binding_del(binding_index=binding_index[i])
|
||||
|
||||
def test_pnat_wildcard_proto(self):
|
||||
"""
|
||||
PNAT test wildcard IP protocol, PNAT_PROTO for mask should be set by
|
||||
handler
|
||||
"""
|
||||
|
||||
PNAT_IP4_INPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_INPUT
|
||||
PNAT_IP4_OUTPUT = \
|
||||
VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_OUTPUT
|
||||
|
||||
tests = [
|
||||
{
|
||||
'input': PNAT_IP4_INPUT,
|
||||
'sw_if_index': self.pg0.sw_if_index,
|
||||
'match': {'mask': 0x2, 'dst': '10.10.10.10'},
|
||||
'rewrite': {'mask': 0x2, 'dst': self.pg1.remote_ip4},
|
||||
'send': (IP(src=self.pg0.remote_ip4, dst='10.10.10.10')),
|
||||
'reply': (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
|
||||
},
|
||||
{
|
||||
'input': PNAT_IP4_OUTPUT,
|
||||
'sw_if_index': self.pg1.sw_if_index,
|
||||
'match': {'mask': 0x1, 'src': self.pg0.remote_ip4},
|
||||
'rewrite': {'mask': 0x1, 'src': '11.11.11.11'},
|
||||
'send': (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)),
|
||||
'reply': (IP(src='11.11.11.11', dst=self.pg1.remote_ip4))
|
||||
},
|
||||
]
|
||||
|
||||
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
||||
for t in tests:
|
||||
rv = self.vapi.pnat_binding_add(match=t['match'],
|
||||
rewrite=t['rewrite'])
|
||||
self.vapi.pnat_binding_attach(sw_if_index=t['sw_if_index'],
|
||||
attachment=t['input'],
|
||||
binding_index=rv.binding_index)
|
||||
|
||||
reply = t['reply']
|
||||
reply[IP].ttl -= 1
|
||||
rx = self.send_and_expect(self.pg0, p_ether / t['send'] * 1,
|
||||
self.pg1)
|
||||
for p in rx:
|
||||
self.validate(p[1], reply)
|
||||
|
||||
self.ping_check()
|
||||
|
||||
self.vapi.pnat_binding_detach(sw_if_index=t['sw_if_index'],
|
||||
attachment=t['input'],
|
||||
binding_index=rv.binding_index)
|
||||
self.vapi.pnat_binding_del(binding_index=rv.binding_index)
|
||||
|
||||
def test_pnat_wildcard_proto_v2(self):
|
||||
""" PNAT test wildcard IP protocol using pnat_binding_add_v2"""
|
||||
|
||||
PNAT_IP4_INPUT = VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_INPUT
|
||||
PNAT_IP4_OUTPUT = \
|
||||
VppEnum.vl_api_pnat_attachment_point_t.PNAT_IP4_OUTPUT
|
||||
|
||||
tests = [
|
||||
{
|
||||
'input': PNAT_IP4_INPUT,
|
||||
'sw_if_index': self.pg0.sw_if_index,
|
||||
'match': {'mask': 0x42, 'dst': '10.10.10.10'},
|
||||
'rewrite': {'mask': 0x42, 'dst': self.pg1.remote_ip4},
|
||||
'send': (IP(src=self.pg0.remote_ip4, dst='10.10.10.10')),
|
||||
'reply': (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4))
|
||||
},
|
||||
{
|
||||
'input': PNAT_IP4_OUTPUT,
|
||||
'sw_if_index': self.pg1.sw_if_index,
|
||||
'match': {'mask': 0x41, 'src': self.pg0.remote_ip4},
|
||||
'rewrite': {'mask': 0x41, 'src': '11.11.11.11'},
|
||||
'send': (IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)),
|
||||
'reply': (IP(src='11.11.11.11', dst=self.pg1.remote_ip4))
|
||||
},
|
||||
]
|
||||
|
||||
p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
|
||||
for t in tests:
|
||||
rv = self.vapi.pnat_binding_add_v2(match=t['match'],
|
||||
rewrite=t['rewrite'])
|
||||
self.vapi.pnat_binding_attach(sw_if_index=t['sw_if_index'],
|
||||
attachment=t['input'],
|
||||
binding_index=rv.binding_index)
|
||||
|
||||
reply = t['reply']
|
||||
reply[IP].ttl -= 1
|
||||
rx = self.send_and_expect(self.pg0, p_ether / t['send'] * 1,
|
||||
self.pg1)
|
||||
for p in rx:
|
||||
self.validate(p[1], reply)
|
||||
|
||||
self.ping_check()
|
||||
|
||||
self.vapi.pnat_binding_detach(sw_if_index=t['sw_if_index'],
|
||||
attachment=t['input'],
|
||||
binding_index=rv.binding_index)
|
||||
self.vapi.pnat_binding_del(binding_index=rv.binding_index)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
||||
Reference in New Issue
Block a user