You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: mesh.rs
    path of file: ./repos/mirrord/mirrord/agent/src/steal/ip_tables
    
    the code of the file until where you have to start completion: use std::sync::{Arc, LazyLock};

use async_trait::async_trait;
use fancy_regex::Regex;
use mirrord_protocol::{MeshVendor, Port};

use crate::{
    error::Result,
    steal::ip_tables::{
        output::OutputRedirect, prerouting::PreroutingRedirect, redirect::Redirect, IPTables,
        IPTABLE_MESH,
    },
};

static LINKERD_SKIP_PORTS_LOOKUP_REGEX: LazyLock<Regex> =
    LazyLock::new(|| Regex::new(r"-p tcp -m multiport --dports ([\d:,]+)").unwrap());

static ISTIO_SKIP_PORTS_LOOKUP_REGEX: LazyLock<Regex> =
    LazyLock::new(|| Regex::new(r"-p tcp -m tcp --dport ([\d:,]+)").unwrap());

pub(crate) struct MeshRedirect<IPT: IPTables> {
    prerouteing: PreroutingRedirect<IPT>,
    output: OutputRedirect<IPT>,
}

impl<IPT> MeshRedirect<IPT>
where
    IPT: IPTables,
{
    pub fn create(ipt: Arc<IPT>, vendor: MeshVendor) -> Result<Self> {
        let prerouteing = PreroutingRedirect::create(ipt.clone())?;

        for port in Self::get_skip_ports(&ipt, &vendor)? {
            prerouteing.add_rule(&format!("-m multiport -p tcp ! --dports {port} -j RETURN"))?;
        }

        let output = OutputRedirect::create(ipt, IPTABLE_MESH.to_string())?;

        Ok(MeshRedirect {
            prerouteing,
            output,
        })
    }

    pub fn load(ipt: Arc<IPT>, _vendor: MeshVendor) -> Result<Self> {
        let prerouteing = PreroutingRedirect::load(ipt.clone())?;
        let output = OutputRedirect::load(ipt, IPTABLE_MESH.to_string())?;

        Ok(MeshRedirect {
            prerouteing,
            output,
        })
    }

    fn get_skip_ports(ip
    
    async fn add_redirect() {
        let gid = getgid();
        let mut mock = MockIPTables::new();

        create_mesh_list_values(&mut mock);

        mock.expect_create_chain()
            .with(eq(IPTABLE_PREROUTING.as_str()))
            .times(1)
            .returning(|_| Ok(()));

        mock.expect_insert_rule()
            .with(
                eq(IPTABLE_PREROUTING.as_str()),
                eq("-m tcp -p tcp --dport 69 -j REDIRECT --to-ports 420"),
                eq(1),
            )
            .times(1)
            .returning(|_, _, _| Ok(()));

        mock.expect_create_chain()
            .with(eq(IPTABLE_MESH.as_str()))
            .times(1)
            .returning(|_| Ok(()));

        mock.expect_insert_rule()
            .with(
                eq(IPTABLE_MESH.as_str()),
                eq(format!("-m owner --gid-owner {gid} -p tcp -j RETURN")),
                eq(1),
            )
            .times(1)
            .returning(|_, _, _| Ok(()));

        mock.expect_insert_rule()
            .with(
                eq(IPTABLE_MESH.as_str()),
                eq("-o lo -m tcp -p tcp --dport 69 -j REDIRECT --to-ports 420"),
                eq(2),
            )
            .times(1)
            .returning(|_, _, _| Ok(()));

        mock.expect_remove_chain()
            .with(eq(IPTABLE_PREROUTING.as_str()))
            .times(1)
            .returning(|_| Ok(()));

        mock.expect_remove_chain()
            .with(eq(IPTABLE_MESH.as_str()))
            .times(1)
            .returning(|_| Ok(()));

        let prerouting =
            MeshRedirect::create(Arc::new(mock), MeshVendor::Linkerd).expect("Unable to create");

        assert!(prerouting.add_redirect(69, 420).await.is_ok());
    }