Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Datapath Probe Cli and Document (#5554)
Signed-off-by: Saurabh Mehra <saurabhmehra@fb.com>
- Loading branch information
1 parent
d5572e3
commit f5e97cd
Showing
3 changed files
with
189 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--- | ||
id: dp_probe_cli | ||
title: Data Path Probe Cli Command | ||
hide_title: true | ||
--- | ||
# dp_probe_cli | ||
|
||
## Overview: | ||
|
||
This command helps an operator to probe the Datapath to the UE. | ||
|
||
|
||
### Usage | ||
|
||
``` | ||
# On your GW host, run the following command | ||
$ dp_probe_cli.py -i <IMSI> | ||
$ dp_probe_cli.py -i 1010000051011 | ||
IMSI: 1010000051011, IP: 192.168.128.15 | ||
Running: sudo ovs-appctl ofproto/trace gtp_br0 tcp,in_port=local,ip_dst=192.168.128.15,ip_src=8.8.8.8,tcp_src=80,tcp_dst=3372 | ||
Datapath Actions: set(tunnel(tun_id=0x1000308,dst=10.0.2.240,ttl=64,tp_dst=2152,flags(df|key))),pop_eth,2 | ||
# You can also supply the followin options | ||
# -I <External IP Address> | ||
# -P <External Port> | ||
# -UP <UE Port> | ||
# -p <Protocol tcp/udp/icmp> | ||
$ dp_probe_cli.py -i 1010000051016 -I 4.2.2.2 -p tcp -P 8080 -UP 3172 | ||
IMSI: 1010000051016, IP: 192.168.128.14 | ||
Running: sudo ovs-appctl ofproto/trace gtp_br0 tcp,in_port=local,ip_dst=192.168.128.14,ip_src=4.2.2.2,tcp_src=8080,tcp_dst=3172 | ||
Datapath Actions: set(tunnel(tun_id=0x1000208,dst=10.0.2.240,ttl=64,tp_dst=2152,flags(df|key))),pop_eth,2 | ||
``` | ||
|
||
|
||
|
||
### What is this command doing? | ||
|
||
This command is a wrapper around *ovs-appctl ofproto/trace* which simulates the Datapath of the packet. | ||
|
||
|
||
### How to read the Output? | ||
|
||
Based on the *IMSI* supplied to this command: | ||
- If the UE is not connected, the command will output ***UE is not connected*** | ||
- If the UE is connected, it prints the *IP Address* of the UE and the Datapath Actions based on the ovs-appctl ofproto/trace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#!/usr/bin/env python3 | ||
|
||
""" | ||
Copyright 2020 The Magma Authors. | ||
This source code is licensed under the BSD-style license found in the | ||
LICENSE file in the root directory of this source tree. | ||
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. | ||
""" | ||
|
||
import argparse | ||
import re | ||
import subprocess | ||
|
||
from lte.protos.mconfig import mconfigs_pb2 | ||
from magma.common.service import MagmaService | ||
|
||
def create_parser(): | ||
""" | ||
Creates the argparse parser with all the arguments. | ||
""" | ||
parser = argparse.ArgumentParser( | ||
description="CLI wrapper around ovs-appctl ofproto/trace.\n" | ||
"To display the Datapath actions of the supplied IMSI", | ||
formatter_class=argparse.ArgumentDefaultsHelpFormatter, | ||
) | ||
parser.add_argument("-i", "--imsi", help="IMSI of the subscriber") | ||
parser.add_argument("-I", "--ip", help="External IP") | ||
parser.add_argument("-P", "--port", help="External Port") | ||
parser.add_argument("-UP", "--ue_port", help="UE Port") | ||
parser.add_argument("-p", "--protocol", help="Portocol (i.e. tcp, udp, icmp)") | ||
|
||
return parser | ||
|
||
|
||
def find_ue_ip(imsi: str): | ||
""" | ||
Finds the UE IP address corresponding to the IMSI | ||
""" | ||
cmd = ["mobility_cli.py", "get_subscriber_table"] | ||
output = subprocess.check_output(cmd) | ||
output_str = str(output, "utf-8").strip() | ||
pattern = "IMSI.*?" + imsi + ".*?([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})" | ||
match = re.search(pattern, output_str) | ||
if match: | ||
return match.group(1) | ||
else: | ||
return "NA" | ||
|
||
|
||
def output_datapath_actions( | ||
ue_ip: str, external_ip: str, external_port: str, ue_port: str, protocol: str | ||
): | ||
""" | ||
Returns the Output of Datapath Actions based as per the supplied UE IP | ||
""" | ||
service = MagmaService("pipelined", mconfigs_pb2.PipelineD()) | ||
if service.mconfig.nat_enabled: | ||
in_port = "local" | ||
else: | ||
in_port = "patch-up" | ||
|
||
cmd = ["sudo", "ovs-appctl", "ofproto/trace", "gtp_br0"] | ||
|
||
cmd_append = ( | ||
protocol + ",in_port=" + in_port + ",ip_dst=" + ue_ip + ",ip_src=" + external_ip | ||
) | ||
|
||
if protocol != "icmp": | ||
cmd_append += ( | ||
"," | ||
+ protocol | ||
+ "_src=" | ||
+ external_port | ||
+ "," | ||
+ protocol | ||
+ "_dst=" | ||
+ ue_port | ||
) | ||
|
||
cmd.append(cmd_append) | ||
|
||
print("Running: " + " ".join(cmd)) | ||
output = subprocess.check_output(cmd) | ||
output_str = str(output, "utf-8").strip() | ||
pattern = "Datapath\sactions:(.*)" | ||
match = re.search(pattern, output_str) | ||
if match: | ||
return match.group(1).strip() | ||
else: | ||
return "NA" | ||
|
||
|
||
def get_options(args): | ||
external_ip = args.ip if args.ip else "8.8.8.8" | ||
external_port = args.port if args.port else "80" | ||
ue_port = args.ue_port if args.ue_port else "3372" | ||
protocol = args.protocol if args.protocol else "tcp" | ||
|
||
return { | ||
"external_ip": external_ip, | ||
"external_port": external_port, | ||
"ue_port": ue_port, | ||
"protocol": protocol, | ||
} | ||
|
||
|
||
def main(): | ||
parser = create_parser() | ||
# Parse the args | ||
args = parser.parse_args() | ||
if not args.imsi: | ||
parser.print_usage() | ||
exit(1) | ||
ue_ip = find_ue_ip(args.imsi) | ||
if ue_ip == "NA": | ||
print("UE is not connected") | ||
exit(1) | ||
|
||
print("IMSI: " + args.imsi + ", IP: " + ue_ip) | ||
|
||
input_options = get_options(args) | ||
dp_actions = output_datapath_actions( | ||
ue_ip, | ||
input_options["external_ip"], | ||
input_options["external_port"], | ||
input_options["ue_port"], | ||
input_options["protocol"], | ||
) | ||
|
||
print("Datapath Actions: " + dp_actions) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |