Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/router.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/router.py	(revision 39323)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/router.py	(working copy)
@@ -15,6 +15,13 @@
 from apv.company import *
 import re
 import time
+from hive.node import AppNode
+from hive.utils import get_system_info, get_current_lang
+from hive.lang import get_langs_info
+from djproject.an_settings import THEMES
+from django.utils.translation import ugettext_lazy as _
+# Available user manual to choose from
+MANUAL = [(_('Application Guide'),'app'), (_('CLI Handbook'), 'cli')]
 
 lruCache = LRUCacheDict(max_size=10000)
 reader = database.Reader('/ca/webui/conf/GeoLite2-City.mmdb')
@@ -801,3 +808,28 @@
     response['Content-Type'] = 'text/plain; charset=utf-8'
     response['Content-Disposition'] = 'attachment; filename=%s' % file_name
     return response
+
+def get_geneve_page(request):
+    andebug("hive.debug", "get_geneve_page")
+    env = HiveEnvironment(loader=ChoiceLoader([
+                                      PackageLoader('apv', 'templates'),
+                                      PackageLoader('hive', 'templates')]))
+    template = env.get_template("/network/interface/geneve_interface/interface.html")
+    ctx = context_for_model(request)
+    response = HttpResponse(template.render(ctx))
+    return response
+
+def context_for_model(request):
+    sess = get_current_session()
+    app_node = AppNode.get_app('apv')
+    django_ctx = RequestContext(request)
+    login_check_data = False
+    if sess.is_login_check():
+        sess.disable_login_check()
+        login_check_data = True
+    system_info = get_system_info()
+    ha_info = get_ha_info()
+    return {'NODE':app_node, 'REQUEST':request, 'SESSION':sess, 'LOGIN_CHECK':login_check_data, 'SYS_INFO':system_info, 'HA_INFO':ha_info,
+            'LANGUAGE_CODE':django_ctx['LANGUAGE_CODE'], 'LANGS':get_langs_info(), 'TRADEMASK':COMPANY_TRADEMASK, 'app_name': PRODUCT_KEYWORD,
+            'MEDIA':'/media/', 'APPNODE':AppNode.get_app('apv'),'COPYRIGHT':COMPANY_COPYRIGHT[get_current_lang()],'COPYRIGHT_CN':COMPANY_COPYRIGHT_CN[get_current_lang()],
+            'csrf_token':django_ctx['csrf_token'], 'THEMES':THEMES, 'PARAMS':{}, 'MANUAL':MANUAL}
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/network/interface/geneve_interface/interface.html
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/network/interface/geneve_interface/interface.html	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/network/interface/geneve_interface/interface.html	(working copy)
@@ -0,0 +1,1307 @@
+{% extends "page_model.html" %}
+
+{% block content %}
+<div class="geneve_container" id="app">
+    <div class="horizontal-nav">
+        <div class="crumbs">
+            <a href="/apv/network/interface/sys_interface"><i class="fa fa-home"></i></a>
+        </div>
+        <ul class="nav nav-tabs">
+            <li>
+                <a href="/apv/network/interface/sys_interface">System Interface</a>
+            </li>
+            <li class="active">
+                <a href="/apv/network/interface/geneve_interface">Geneve Interface</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/bond_interface">Bond Interface</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/vlan_interface">VLAN Interface</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/vxlan_interface">VXLAN Interface</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/mnet_interface">MNET Interface</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/interface_bandwidth">Interface Bandwidth</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/global_lldp_settings">Global LLDP Settings</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/interface_stats">Interface Configuration &amp; Statistics</a>
+            </li>
+            <li>
+                <a href="/apv/network/interface/port_map">NIC Port Status</a>
+            </li>
+        </ul>
+    </div>
+    <nav class="head-nav " role="navigation">
+        <div class="btn-group btn-config" style="">
+            <button type="button" class="btn btn-action dropdown-toggle" data-toggle="dropdown">
+                <i class="fa fa-cog"></i>
+            </button>
+            <ul class="dropdown-menu" style="" role="menu">
+                <li class="config-upload">
+                    <span class="fileinput-button">
+                        <i class="fa fa-sign-in"></i>
+                        <span>&nbsp;&nbsp;Import</span>
+                        <input id="fileupload" type="file" name="files[]">
+                    </span>
+                </li>
+                <li class="divider"></li>
+                <li class="config-download">
+                    <span class="filedownload-button">
+                        <i class="fa fa-sign-out"></i>
+                        <span>&nbsp;&nbsp;Export</span>
+                    </span>
+                </li>
+            </ul>
+        </div>
+        <div class="btn-group btn-config" style="display:none;">
+            <img src="/media/img/Webroot-logo.png">
+        </div>
+        <a class="model-name" href="#" style="width:90%;"><i class="fa fa-folder-open"></i> {[urlParams.title]}</a>
+    </nav>
+    <ul class="config-nav nav nav-pills">
+        <li :class="{ active: panel_active === 0 }">
+            <a class="config-nav-a" @click="changePanel(0)">{% trans %}Basic Settings{% endtrans %} <i class="fa fa-wrench"></i></a>
+        </li>
+        <li :class="{ active: panel_active === 1 }">
+            <a class="config-nav-a" @click="changePanel(1)">Forwarding Entry<i class="fa fa-wrench"></i></a>
+        </li>
+    </ul>
+    <div class="geneve-main">
+        <div
+            v-show="panel_active === 0"
+            class="content"
+        >
+            <div class="btn-static" v-show="showSaveBar">
+                <div class="btn-switch">
+                    <button type="button" class="btn btn-action"
+                        @click="vlan_interface ? bindVlanForGeneveInterface() : unbindVlanForGeneveInterface()"
+                    >
+                        Save Changes
+                    </button>
+                    <button type="button" class="btn btn-default btn-cancel" @click="resetGeneveVlanSetting">Cancel</button>
+                </div>
+            </div>
+            <fieldset>
+                <div class="form-group textinput style-default">
+                    <label class="vlan_title col-md-offset-3 control-label">VLAN Interface&nbsp;</label>
+                    <div class="assobox clearfix">
+                        <div class="pull-left assobox-container assoinput">
+                            <input id="vlan_interface" type="text" v-model="vlan_interface" readonly />
+                            <div class="vlan_name_ctlgrp">
+                                <i @click="toogleVlanPanel()" v-if="!vlan_panel" class="asso-sign fa fa-list-alt"></i>
+                                <i v-if="vlan_panel && !vlan_interface" class="select-btn fa arrow-circle-left" @click="selectVlanInterface"></i>
+                                <i v-if="vlan_panel && vlan_interface" class="deselect-btn fa arrow-circle-right" @click="deselectVlanInterface"></i>
+                            </div>
+                        </div>
+                        <div v-if="vlan_panel" class="pull-left assobox-container">
+                            <select multiple="multiple" v-model="selectedVlanInterface">
+                                <option v-for="item in filteredVlanList" :key="item.key" :value="item.key">{[ item.label ]}</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </fieldset>
+            <el-alert
+                v-if="showVlanClearWarning"
+                title="Warning: please also clear geneve local forwarding table after this operation."
+                type="warning"
+                show-icon
+                :closable="true"
+                class="fixed-vlan-warning"
+            ></el-alert>
+            <div class="interface-settings datatable table-box">
+                <div class="box-title">
+                    Tunnel Binding
+                </div>
+                <div class="box-header">
+                    <div class="box-bg-spe">
+                        <div class="box-icon-title">
+                            <i class="fa fa-list-alt"></i>
+                        </div>
+                    </div>
+                    <div class="control-group table-btn-group">
+                        <button @click="new_tunnel_binding_show = true" type="button" class="btn btn-action add-btn"><i class="fa fa-plus-circle"></i>ADD</button>
+                        <button @click="deleteGeneveTunnelForInterface()" type="button" class="btn btn-action delete-btn" :class="{ disabled: interfaceSettingDeleteStatus }"><i class="fa fa-minus-circle"></i>DELETE</button>
+                        <div class="btn-group">
+                            <button type="button" class="btn btn-action clear-btn dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                ACTIONS <span class="caret"></span>
+                            </button>
+                            <ul class="dropdown-menu dropdown-menu-right">
+                                <li>
+                                    <a href="#" @click.prevent="clearAllDynamicForwardEntry()">Clear Dynamic</a>
+                                </li>
+                                <li>
+                                    <a href="#" @click.prevent="clearAllStaticForwardEntry()">Clear Static</a>
+                                </li>
+                            </ul>
+                        </div>
+                    </div>
+                    <div class="pull-right filter-control-group">
+                    </div>
+                </div>
+                <table id="tunnel_binding" class="display" style="width:100%">
+                    <thead>
+                        <tr>
+                            <th>ID</th>
+                            <th>{% trans %}Tunnel Name{% endtrans %}</th>
+                            <th>{% trans %}Local IP{% endtrans %}</th>
+                            <th>{% trans %}Remote IP{% endtrans %}</th>
+                        </tr>
+                    </thead>
+                </table>
+            </div>
+        </div>
+        <div
+            v-show="panel_active === 1"
+            class="content"
+        >
+            <div class="interface-settings datatable table-box">
+                <div class="box-header">
+                    <div class="box-bg-spe">
+                        <div class="box-icon-title">
+                            <i class="fa fa-list-alt"></i>
+                        </div>
+                    </div>
+                    <div class="control-group table-btn-group">
+                        <button @click="new_forward_entry_show = true" type="button" class="btn btn-action add-btn"><i class="fa fa-plus-circle"></i>ADD</button>
+                        <button @click="deleteForwardEntry()" type="button" class="btn btn-action delete-btn" :class="{ disabled: forwardEntryDeleteStatus }"><i class="fa fa-minus-circle"></i>DELETE</button>
+                        <div class="btn-group">
+                            <button type="button" class="btn btn-action clear-btn dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                ACTIONS <span class="caret"></span>
+                            </button>
+                            <ul class="dropdown-menu dropdown-menu-right">
+                                <li>
+                                    <a href="#" @click.prevent="clearAllDynamicForwardEntry()">Clear Dynamic</a>
+                                </li>
+                                <li>
+                                    <a href="#" @click.prevent="clearAllStaticForwardEntry()">Clear Static</a>
+                                </li>
+                            </ul>
+                        </div>
+                    </div>
+                    <div class="pull-right filter-control-group">
+                    </div>
+                </div>
+                <table id="forward_entry" class="display" style="width:100%">
+                    <thead>
+                        <tr>
+                            <th>ID</th>
+                            <th>{% trans %}MAC{% endtrans %}</th>
+                            <th>{% trans %}GTEP-IP{% endtrans %}</th>
+                            <th>{% trans %}VLAN{% endtrans %}</th>
+                            <th>{% trans %}Type{% endtrans %}</th>
+                            <th>{% trans %}Location{% endtrans %}</th>
+                        </tr>
+                    </thead>
+                </table>
+            </div>
+        </div>
+
+        <transition name="fade">
+            <div
+                class="new_lightbox"
+                v-if="new_tunnel_binding_show"
+                v-cloak
+            >
+                <div class="lightbox-close"
+                    @click="new_tunnel_binding_show = false"
+                >
+                    <i class="fa modal-close-icon">×</i>
+                </div>
+                <div class="lightbox-container">
+                    <div class="lightbox-box">
+                        <div class="lightbox-header">
+                            <span class="lightbox-title">
+                                <div class="box-icon-title">
+                                    <i class="fa fa-plus-circle"></i>
+                                </div>
+                                <div>Bind GENEVE Tunnel for {[urlParams.title]}</div>
+                            </span>
+                        </div>
+                        <div class="lightbox-content">
+                            <fieldset>
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">Tunnel Name&nbsp;</label>
+                                    <div class="assobox clearfix">
+                                        <div class="pull-left assobox-container assoinput">
+                                            <input id="tunnel_name" type="text" v-model="tunnel_name" readonly />
+                                            <div class="tunnel_name_ctlgrp">
+                                                <i @click="toogleTunnelName()" v-if="!tunnel_name_panel" class="asso-sign fa fa-list-alt"></i>
+                                                <i v-if="tunnel_name_panel && !tunnel_name" class="select-btn fa arrow-circle-left" @click="selectTunnelName"></i>
+                                                <i v-if="tunnel_name_panel && tunnel_name" class="deselect-btn fa arrow-circle-right" @click="deselectTunnelName"></i>
+                                            </div>
+                                        </div>
+                                        <div v-if="tunnel_name_panel" class="pull-left assobox-container">
+                                            <select multiple="multiple" v-model="selectedTunnelName">
+                                                <option v-for="item in filteredHostList" :key="item.name" :value="item.name">{[ item.name ]}</option>
+                                            </select>
+                                        </div>
+                                    </div>
+                                </div>
+                            </fieldset>
+                            <div class="btn-box col-md-offset-3">
+                                <button
+                                    @click="bindGeneveTunnelForInterface()"
+                                    type="button"
+                                    class="btn btn-action"
+                                    :disabled="!tunnel_name"
+                                >
+                                    Bind the GENEVE Tunnel
+                                </button>
+                                <button @click="new_tunnel_binding_show = false" type="button" class="btn btn-default btn-cancel">Cancel</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </transition>
+
+        <transition name="fade">
+            <div
+                class="new_lightbox"
+                v-if="new_forward_entry_show"
+                v-cloak
+            >
+                <div class="lightbox-close"
+                    @click="new_forward_entry_show = false"
+                >
+                    <i class="fa modal-close-icon">×</i>
+                </div>
+                <div class="lightbox-container">
+                    <div class="lightbox-box">
+                        <div class="lightbox-header">
+                            <span class="lightbox-title">
+                                <div class="box-icon-title">
+                                    <i class="fa fa-plus-circle"></i>
+                                </div>
+                                <div>New GENEVE Forwarding Entry</div>
+                            </span>
+                        </div>
+                        <div class="lightbox-content">
+                            <fieldset>
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">Location&nbsp;</label>
+                                    <div>
+                                        <select v-model="forwardEntryForm.location" id="location_select">
+                                            <option value="local">local</option>
+                                            <option value="remote">remote</option>
+                                        </select>
+                                    </div>
+                                </div>
+                            </fieldset>
+                            <fieldset>
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">MAC*&nbsp;</label>
+                                    <div>
+                                        <input type="text" v-model="forwardEntryForm.mac" placeholder="">
+                                    </div>
+                                </div>
+                            </fieldset>
+                            <fieldset v-if="forwardEntryForm.location === 'remote'">
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">GTEP-IP&nbsp;</label>
+                                    <div>
+                                        <input type="text" v-model="forwardEntryForm.gtep" placeholder="">
+                                    </div>
+                                </div>
+                            </fieldset>
+                            <div class="btn-box col-md-offset-3">
+                                <button @click="addForwardEntry" type="button" class="btn btn-action">Bind the GENEVE Tunnel</button>
+                                <button @click="new_forward_entry_show = false" type="button" class="btn btn-default btn-cancel">Cancel</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </transition>
+    </div>
+</div>
+<script type="text/javascript">
+    require(['vue', 'list-list'], function(Vue){
+        var v = new Vue({
+            delimiters: ['{[', ']}'],
+            el: "#app",
+            data: function() {
+                return {
+                    geneve_con_text: 'test',
+                    panel_active: 0,
+                    selectedTokens: [],
+                    selectedForwardEntryTokens: [],
+                    forwardEntryDeleteStatus: true,
+                    interfaceSettingDeleteStatus: true,
+                    urlParams: {},
+                    new_tunnel_binding_show: false,
+                    new_forward_entry_show: false,
+                    tunnel_name_loading: false,
+                    tunnel_name_panel: false,
+                    tunnel_name: '',
+                    selectedTunnelName: [],
+                    host_list_for_tunnel_name: [],
+                    vlan_panel: false,
+                    vlan_interface: '',
+                    originalVlanInterface: '',
+                    selectedVlanInterface: [],
+                    vlan_list: [],
+                    forwardEntryForm: {
+                        location: 'local',
+                        mac: '',
+                        gtep: ''
+                    },
+                    showSaveBar: false,
+                    showVlanClearWarning: false,
+                };
+            },
+            computed: {
+                filteredHostList() {
+                    if (this.tunnel_name) {
+                        return this.host_list_for_tunnel_name.filter(item => item.name !== this.tunnel_name);
+                    }
+                    return this.host_list_for_tunnel_name;
+                },
+                filteredVlanList() {
+                    if (this.vlan_interface) {
+                        return this.vlan_list.filter(item => item.key !== this.vlan_interface);
+                    }
+                    return this.vlan_list;
+                },
+            },
+            mounted: function () {
+                const self = this;
+                self.parseUrlParams();
+                self.vlan_interface = self.urlParams.vlan;
+                self.originalVlanInterface = self.vlan_interface;
+                self.$watch('vlan_interface', function(newVal, oldVal) {
+                    if (newVal !== oldVal) {
+                        self.showSaveBar = true;
+                    }
+                    if (oldVal && !newVal) {
+                        self.showVlanClearWarning = true;
+                    } else {
+                        self.showVlanClearWarning = false;
+                    }
+                });
+                self.$watch('panel_active', function(val) {
+                    self.redrawAllDataTables();
+                });
+                self.getVlanList();
+                self.getBondGeneveTunnelList();
+                self.getForwardEntryList();
+                self.getGeneveTunnelList();
+            },
+            methods: {
+                changePanel: function(panel) {
+                    this.panel_active = panel;
+                },
+                initDataTable: function() {
+                    if ($.fn.DataTable.isDataTable('#tunnel_binding')) {
+                        $('#tunnel_binding').DataTable().destroy();
+                    }
+                    if ($.fn.DataTable.isDataTable('#forward_entry')) {
+                        $('#forward_entry').DataTable().destroy();
+                    }
+                },
+                tunnelNameFilterMethod: function(query, item) {
+                    return item.label.indexOf(query) > -1;
+                },
+                getGeneveTunnelList: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/Tunnel/_config_table',
+                        type: 'POST',
+                        dataType: "json",
+                        data: {
+                            draw:1,
+                            columns: [
+                                {
+                                    data:"name",
+                                    name:"name",
+                                    searchable:true,
+                                    orderable:false,
+                                    search: {
+                                        value: "",
+                                        regex: false
+                                    }
+                                },
+                                {
+                                    data:"local_ip",
+                                    name:"local_ip",
+                                    searchable:true,
+                                    orderable:true,
+                                    search: {
+                                        value: "",
+                                        regex: false
+                                    }
+                                },
+                                {
+                                    data:"remote_ip",
+                                    name:"remote_ip",
+                                    searchable:true,
+                                    orderable:true,
+                                    search: {
+                                        value: "",
+                                        regex: false
+                                    }
+                                }
+                            ],
+                            start:0,
+                            length:100,
+                            search: {
+                                value: "",
+                                regex: false
+                            }
+                        },
+                        success: function(res) {
+                            self.host_list_for_tunnel_name = res.data
+                        }
+                    });
+                },
+                populateTunnelBinding: function(data) {
+                    var self = this;
+                    $('#tunnel_binding').DataTable({
+                        data: data,
+                        columns: [
+                            {
+                            title: "<input type='checkbox' id='select-all' />",
+                            data: null,
+                            width: "40px",
+                            className: "dt-checkbox-col",
+                            render: function(data, type, row) {
+                                return `<input type='checkbox' class='select-checkbox' value='${row.name}' />`;
+                            },
+                                orderable: false
+                            },
+                            { title: "Tunnel Name", data: "name" },
+                            { title: "Local IP", data: "local" },
+                            { title: "Remote IP", data: "remote" }
+                        ],
+                        destroy: true,
+                        scrollX: true
+                    });
+                    $('#select-all').on('click', function() {
+                        var rows = $('#tunnel_binding').DataTable().rows({ 'search': 'applied' }).nodes();
+                        $('input[type="checkbox"]', rows).prop('checked', this.checked);
+                        self.updateSelectedTokens();
+                    });
+                    $('#tunnel_binding tbody').on('change', 'input[type="checkbox"]', function() {
+                        if (!this.checked) {
+                            var el = $('#select-all').get(0);
+                            if (el && el.checked && ('indeterminate' in el)) {
+                                el.indeterminate = true;
+                            }
+                        }
+                        self.updateSelectedTokens();
+                    });
+                },
+                populateForwardEntry: function(data) {
+                    var self = this;
+                    $('#forward_entry').DataTable({
+                        data: data,
+                        columns: [
+                            {
+                                title: "<input type='checkbox' id='select-all-fe' />",
+                                data: null,
+                                width: "40px",
+                                className: "dt-checkbox-col",
+                                render: function(data, type, row) {
+                                    return `<input type='checkbox' class='select-checkbox' value='${encodeURIComponent(JSON.stringify(row))}' />`;
+                                },
+                                orderable: false
+                            },
+                            { title: "MAC",data: "mac" },
+                            { title: "GTEP-IP", data: "gtep" },
+                            { title: "VLAN", data: "vlan" },
+                            { title: "Type", data: "type" },
+                            { title: "Location", data: "location" }
+                        ],
+                        destroy: true,
+                        scrollX: true
+                    });
+                    $('#select-all-fe').on('click', function() {
+                        var rows = $('#forward_entry').DataTable().rows({ 'search': 'applied' }).nodes();
+                        $('input[type="checkbox"]', rows).prop('checked', this.checked);
+                        self.updateForwardEntryTokens();
+                    });
+                    $('#forward_entry tbody').off('change', 'input[type="checkbox"]'); // 先移除舊的事件
+                    $('#forward_entry tbody').on('change', 'input[type="checkbox"]', function() {
+                        self.updateForwardEntryTokens();
+                    });
+                },
+                updateForwardEntryTokens: function() {
+                    let selectedTokensTemp = [];
+                    $('#forward_entry tbody input[type="checkbox"]:checked').each(function() {
+                        try {
+                            selectedTokensTemp.push(JSON.parse(decodeURIComponent($(this).val())));
+                        } catch(e) {
+                            selectedTokensTemp.push($(this).val());
+                        }
+                    });
+                    this.selectedForwardEntryTokens = selectedTokensTemp;
+                    selectedTokensTemp.length > 0
+                        ? this.forwardEntryDeleteStatus = false
+                        : this.forwardEntryDeleteStatus = true;
+                },
+                updateSelectedTokens: function() {
+                    let selectedTokensTemp = [];
+                    $('#tunnel_binding tbody input[type="checkbox"]:checked').each(function() {
+                        selectedTokensTemp.push($(this).val());
+                    });
+                    this.selectedTokens = selectedTokensTemp;
+
+                    selectedTokensTemp.length > 0
+                        ? this.interfaceSettingDeleteStatus = false
+                        : this.interfaceSettingDeleteStatus = true;
+                },
+                getGeneveConfiguration: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/prometheus/Log/_field_group?name=get',
+                        type: 'GET',
+                        cache: false,
+                        dataType: 'json'
+                    }).then(function(data){
+                        self.geneve_con_text = data.content;
+                    });
+                },
+                redrawAllDataTables: function() {
+                    if ($.fn.DataTable.isDataTable('#tunnel_binding')) {
+                        $('#tunnel_binding').DataTable().columns.adjust().draw(false);
+                    }
+                    if ($.fn.DataTable.isDataTable('#forward_entry')) {
+                        $('#forward_entry').DataTable().columns.adjust().draw(false);
+                    }
+                },
+                parseUrlParams: function() {
+                    var params = {};
+                    var search = window.location.search;
+                    if (search && search.length > 1) {
+                        var usp = new URLSearchParams(search);
+                        usp.forEach(function(value, key) {
+                            params[key] = value;
+                        });
+                    }
+                    this.urlParams = params;
+                },
+                handleSingleSelect(event) {
+                    const selected = Array.from(event.target.selectedOptions);
+                    if (selected.length > 1) {
+                        const lastSelected = selected[selected.length - 1];
+                        this.selectedValue = lastSelected.value;
+                        Array.from(event.target.options).forEach(opt => {
+                        opt.selected = opt.value === this.selectedValue;
+                        });
+                    }
+                },
+                toogleTunnelName: function() {
+                    this.tunnel_name_panel = !this.tunnel_name_panel;
+                },
+                selectTunnelName: function() {
+                    if (this.selectedTunnelName.length > 0) {
+                        this.tunnel_name = this.selectedTunnelName[0];
+                        this.selectedTunnelName = [];
+                    }
+                },
+                deselectTunnelName: function() {
+                    this.tunnel_name = '';
+                },
+                toogleVlanPanel: function() {
+                    this.vlan_panel = !this.vlan_panel;
+                },
+                selectVlanInterface: function() {
+                    if (this.selectedVlanInterface.length > 0) {
+                        this.vlan_interface = this.selectedVlanInterface[0];
+                        this.selectedVlanInterface = [];
+                    }
+                },
+                deselectVlanInterface: function() {
+                    this.vlan_interface = '';
+                },
+                bindGeneveTunnelForInterface: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/Interface/_perform',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            action: 'BindTunnel',
+                            options: JSON.stringify({
+                                interface: self.urlParams.title,
+                                tunnel: self.tunnel_name
+                            })
+                        },
+                        success: function(res) {
+                            window.location.reload();
+                        }
+                    });
+                },
+                clearGeneveTunnelForInterface: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/Interface/_perform',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            action: 'ClearTunnels',
+                            options: JSON.stringify({
+                                interface: this.urlParams.title
+                            })
+                        },
+                        success: function(res) {
+                            window.location.reload();
+                        }
+                    });
+                },
+                getBondGeneveTunnelList: function() {
+                    var self = this;
+                    var url = '/api/apv/network/geneve/Tunnel/_config_table?initial_filter=' + JSON.stringify({interface: self.urlParams.title});
+                    var postData = {
+                        draw: 1,
+                        columns: [
+                            {
+                                data: "name",
+                                name: "name",
+                                searchable: true,
+                                orderable: false,
+                                search: { value: "", regex: false }
+                            },
+                            {
+                                data: "local_ip",
+                                name: "local_ip",
+                                searchable: true,
+                                orderable: true,
+                                search: { value: "", regex: false }
+                            },
+                            {
+                                data: "remote_ip",
+                                name: "remote_ip",
+                                searchable: true,
+                                orderable: true,
+                                search: { value: "", regex: false }
+                            }
+                        ],
+                        start: 0,
+                        length: 100,
+                        search: { value: "", regex: false }
+                    };
+                    $.ajax({
+                        url: url,
+                        type: 'POST',
+                        dataType: 'json',
+                        data: postData,
+                        success: function(res) {
+                            var arr = Array.isArray(res.data) ? res.data : [];
+                            var mapped = arr.map(function(item) {
+                                return {
+                                    name: item.name,
+                                    local: item.local_ip,
+                                    remote: item.remote_ip
+                                };
+                            });
+                            self.populateTunnelBinding(mapped);
+                        }
+                    });
+                },
+                deleteGeneveTunnelForInterface: function() {
+                    var self = this;
+                    if (!self.selectedTokens || self.selectedTokens.length === 0) {
+                        alert('Please select at least one tunnel to unbind.');
+                        return;
+                    }
+                    var tunnelsStr = self.selectedTokens
+                        .map(function(item) {
+                            var name = typeof item === 'object' && item !== null ? item.name : item;
+                            return JSON.stringify({ name: name });
+                        })
+                        .join('ÿÿÿÿÿ');
+                    $.ajax({
+                        url: '/api/apv/network/geneve/Interface/_perform',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            action: 'UnbindTunnel',
+                            options: JSON.stringify({
+                                interface: self.urlParams.title,
+                                tunnels: tunnelsStr
+                            })
+                        },
+                        success: function(res) {
+                            window.location.reload();
+                        }
+                    })
+                },
+                bindVlanForGeneveInterface: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/Interface/_perform',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            action: 'BindVLAN',
+                            options: JSON.stringify({
+                                interface: self.urlParams.title,
+                                vlan: self.vlan_interface
+                            })
+                        },
+                        success: function(res) {
+                            console.log(res)
+                            if (res[0]) {
+                                window.location.href = '/apv/network/interface/geneve_interface/_list';
+                            } else {
+                                alert(res[1]);
+                            }
+                        }
+                    });
+                },
+                unbindVlanForGeneveInterface: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/Interface/_perform',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            action: 'UnbindVLAN',
+                            options: JSON.stringify({
+                                interface: self.urlParams.title,
+                                vlan: self.urlParams.vlan
+                            })
+                        },
+                        success: function(res) {
+                            window.location.href = '/apv/network/interface/geneve_interface/_list';
+                        }
+                    });
+                },
+                getVlanList: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/interface/VlanInterface/_config_table',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            draw: 1,
+                            columns: [
+                                { data: "name", name: "name", searchable: true, orderable: false, search: { value: "", regex: false } }
+                            ],
+                            start: 0,
+                            length: 100,
+                            search: { value: "", regex: false }
+                        },
+                        success: function(res) {
+                            var arr = Array.isArray(res.data) ? res.data : [];
+                            var mapped = arr.map(function(item) {
+                                return {
+                                    key: item.name,
+                                    label: item.name
+                                };
+                            });
+                            self.vlan_list = mapped;
+                        }
+                    });
+                },
+                addForwardEntryRemote: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/ForwardingEntry/_add',
+                        type: 'POST',
+                        dataType: "json",
+                        data: {
+                            post_data: JSON.stringify({
+                                vni: self.urlParams.vni,
+                                mac: self.forwardEntryForm.mac,
+                                gtep_ip: self.forwardEntryForm.gtep,
+                            })
+                        },
+                        success: function(res) {
+                            if (res[0]) {
+                                window.location.reload();
+                            } else {
+                                alert(res[1]);
+                            }
+                        }
+                    });
+                },
+                addForwardEntryLocal: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/ForwardingEntry/_add',
+                        type: 'POST',
+                        dataType: "json",
+                        data: {
+                            post_data: JSON.stringify({
+                                vni: self.urlParams.vni,
+                                mac: self.forwardEntryForm.mac,
+                            })
+                        },
+                        success: function(res) {
+                            if (res[0]) {
+                                window.location.reload();
+                            } else {
+                                alert(res[1]);
+                            }
+                        }
+                    });
+                },
+                addForwardEntry: function() {
+                    var self = this;
+                    if (self.forwardEntryForm.location === 'local') {
+                        self.addForwardEntryLocal();
+                    } else if (self.forwardEntryForm.location === 'remote') {
+                        self.addForwardEntryRemote();
+                    }
+                },
+                deleteForwardEntry: function() {
+                    var self = this;
+                    if (!self.selectedForwardEntryTokens || self.selectedForwardEntryTokens.length === 0) {
+                        alert('Please select at least one entry to delete.');
+                        return;
+                    }
+                    var entriesStr = self.selectedForwardEntryTokens
+                        .map(function(item) {
+                            return JSON.stringify({ type: item.type, vni: self.urlParams.vni, mac: item.mac });
+                        })
+                        .join('ÿÿÿÿÿ');
+                    $.ajax({
+                        url: '/api/apv/network/geneve/ForwardingEntry/_perform',
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            action: 'Delete',
+                            options: JSON.stringify({
+                                pk: entriesStr
+                            })
+                        },
+                        success: function(res) {
+                            window.location.reload();
+                        }
+                    });
+                },
+                getForwardEntryList: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/ForwardingEntry/_config_table?initial_filter='+ JSON.stringify({vni: self.urlParams.vni}),
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {
+                            draw: 1,
+                            columns: [
+                                { data: "mac", name: "mac", searchable: true, orderable: true, search: { value: "", regex: false } },
+                                { data: "gtep_ip", name: "gtep_ip", searchable: true, orderable: true, search: { value: "", regex: false } },
+                                { data: "vlan", name: "vlan", searchable: true, orderable: true, search: { value: "", regex: false } },
+                                { data: "type", name: "type", searchable: true, orderable: true, search: { value: "", regex: false } },
+                                { data: "location", name: "location", searchable: true, orderable: true, search: { value: "", regex: false } }
+                            ],
+                            start: 0,
+                            length: 100,
+                            search: { value: "", regex: false }
+                        },
+                        success: function(res) {
+                            var arr = Array.isArray(res.data) ? res.data : [];
+                            var mapped = arr.map(function(item) {
+                                return {
+                                    mac: item.mac,
+                                    gtep_ip: item.gtep_ip,
+                                    vlan: item.vlan,
+                                    type: item.type,
+                                    location: item.location
+                                };
+                            });
+                            self.populateForwardEntry(mapped);
+                        }
+                    });
+                },
+                clearAllDynamicForwardEntry: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/ForwardingEntry/_perform',
+                        type: 'POST',
+                        dataType: "json",
+                        data: {
+                            action: 'ClearDynamic',
+                            options: JSON.stringify({
+                                "vni": self.urlParams.vni
+                            })
+                        },
+                        success: function(res) {
+                            console.log(res);
+                        }
+                    });
+                },
+                clearAllStaticForwardEntry: function() {
+                    var self = this;
+                    $.ajax({
+                        url: '/api/apv/network/geneve/ForwardingEntry/_perform',
+                        type: 'POST',
+                        dataType: "json",
+                        data: {
+                            action: 'ClearStatic',
+                            options: JSON.stringify({
+                                "vni": self.urlParams.vni
+                            })
+                        },
+                        success: function(res) {
+                            console.log(res);
+                        }
+                    });
+                },
+                resetGeneveVlanSetting: function() {
+                    this.showSaveBar = false;
+                },
+            }
+        });
+    });
+</script>
+<style scoped>
+    .head-nav {
+        margin-bottom: 0;
+    }
+    .geneve-main {
+        background-color: #03072f;
+        padding: 20px;
+        color: #fff;
+    }
+    .config-nav li{
+        cursor: pointer;
+    }
+    th.dt-checkbox-col, td.dt-checkbox-col {
+        text-align: left;
+    }
+    .vlan_title {
+        width: 10%;
+        margin-left: 25%;
+    }
+    .dataTables_wrapper > .row {
+        margin-left: 0 !important;
+        margin-right: 0 !important;
+    }
+    .dataTables_wrapper .row {
+        align-items: center;
+        height: 40px;
+    }
+    .sorting, .sorting_asc, .sorting_desc {
+        cursor: pointer;
+    }
+    .table-btn-group {
+        margin-bottom: 10px;
+    }
+    .dataTables_wrapper .row {
+        display: flex;
+    }
+    .dataTables_wrapper .dataTables_filter {
+        top: -55px;
+    }
+    .field-group-box fieldset {
+        position: relative;
+    }
+    .main-form .pull-right.nav {
+        left: -10px;
+        top: -50px;
+    }
+    .table-box {
+        position: relative;
+        margin-top: 20px;
+        margin-bottom: 40px;
+    }
+    .box-title {
+        position: absolute;
+        background-color: #75adc9;
+        color: #fff;
+        right: 0;
+        top: -24px;
+        padding: 2px 40px;
+    }
+    .port_number {
+        height: 24px !important;
+        background-color: #1b2d43 !important;
+        color: #fff !important;
+        border: #1b2d43 !important;
+    }
+    .switch {
+        position: relative;
+        display: inline-block;
+        width: 49px;
+        height: 23px;
+    }
+    .switch input {
+        opacity: 0;
+        width: 0;
+        height: 0;
+    }
+    .form-group {
+        display: flex;
+        align-items: flex-start;
+    }
+    .form-group label {
+        margin-top: 8px;
+    }
+    .slider {
+        position: absolute;
+        cursor: pointer;
+        top: 0; left: 0; right: 0; bottom: 0;
+        background-color: #ccc;
+        transition: 0.4s;
+        border-radius: 17px;
+    }
+    .slider:before {
+        position: absolute;
+        content: "";
+        height: 17px;
+        width: 17px;
+        left: 3px;
+        bottom: 3px;
+        background-color: white;
+        transition: 0.4s;
+        border-radius: 50%;
+    }
+    input:checked + .slider {
+        background-color: #2196F3;
+    }
+    input:checked + .slider:before {
+        transform: translateX(26px);
+    }
+    .settings-btn-box {
+        padding-top: 30px;
+        padding-left: 30%;
+        display: flex;
+        flex-direction: column;
+        gap: 8px;
+    }
+    thead {
+        color: #6a7a8c;
+    }
+    tbody>tr:nth-child(odd), .table>tbody>tr:nth-child(odd) {
+        background-color: #121633;
+    }
+
+    .new_lightbox {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: rgba(0, 0, 0, 0.5);
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        z-index: 1000;
+    }
+    .lightbox-close {
+        position: fixed;
+        z-index: 1;
+        top: 0;
+        right: 15px;
+        font-size: 40px;
+        padding: 5px;
+        cursor: pointer;
+        color: #fff;
+    }
+    .lightbox-box {
+        width: 800px;
+        margin: 0 auto;
+    }
+    .lightbox-title {
+        display: flex;
+        align-items: center;
+        gap: 10px;
+        font-size: 14px;
+    }
+    .lightbox-header {
+        display: flex;
+        align-items: center;
+        height: 36px;
+        border-radius: 6px 6px 0 0;
+        color: #fff;
+        background: #1b2d43;
+        padding: 0 20px;
+    }
+    .lightbox-content {
+        background-color: #03072f;
+        padding: 55px 60px 30px;
+    }
+    .lightbox-content fieldset {
+        display: flex;
+        flex-direction: column;
+        gap: 8px;
+    }
+    .lightbox-content fieldset input {
+        background-color: #1b2d43;
+        color: #ccc;
+        border: none;
+        border-radius: 6px;
+        background-clip: padding-box;
+        margin-right: 6px;
+    }
+    .btn-box {
+        margin-top: 30px;
+    }
+
+    .fade-enter-active, .fade-leave-active {
+        transition: opacity 0.3s;
+    }
+    .fade-enter, .fade-leave-to {
+        opacity: 0;
+    }
+    [v-cloak] {
+        display: none !important;
+    }
+
+    .assobox .assobox-nav > li > a {
+    padding: 0 15px;
+        }
+
+    .assobox .assobox-nav > li.active > a {
+        background-color: #121633;
+    }
+
+    .assobox select option {
+        display: table;
+    }
+
+    .assobox select,
+    .assobox .ctlgrp {
+        width: 190px;
+        height: 190px;
+        padding: 2px;
+        border: 1px solid #121633;
+    }
+
+    .assobox .ctlgrp {
+        height: 24px;
+        border-top: none;
+    }
+
+    .assobox .ctlgrp i {
+        font-size: 20px;
+        width: 20px;
+        height: 20px;
+        cursor: pointer;
+        text-align: center;
+        color: #65b6d5;
+    }
+
+    .assobox .select-btn,
+    .assobox .deselect-btn,
+    .assobox .asso-sign {
+        font-size: 16px;
+        line-height: 20px;
+        position: absolute;
+        left: 190px;
+        width: 20px;
+        height: 20px;
+        margin: 4px 2px;
+        cursor: pointer;
+        text-align: center;
+        color: #65b6d5;
+    }
+
+    .assobox .select-btn {
+        top: 75px;
+        left: 0;
+    }
+
+    .assobox .deselect-btn {
+        top: 75px;
+        left: 0;
+    }
+
+    .assobox .asso-sign {
+        left: 0;
+    }
+
+    .assobox .assobox-container {
+        position: relative;
+    }
+    .assoinput {
+        display: flex;
+        height: 190px;
+    }
+    .assobox .assobox-container + .assobox-container {
+        margin-left: 24px;
+    }
+
+    .assobox .chosen.single select {
+        height: 28px;
+    }
+
+    .assobox .chosen.single .select-btn {
+        top: 0;
+    }
+
+    .assobox .chosen.single .deselect-btn {
+        display: none;
+    }
+
+    .assobox .chosen select {
+        height: 190px;
+        color: #65b6d5;
+    }
+
+    .assobox .candidate {
+        display: none;
+    }
+
+    .assobox .candidate.composition {
+        display: block;
+    }
+
+    .assobox .candidate .search-box {
+        display: none;
+        margin-bottom: 10px;
+    }
+
+    .assobox .candidate .search-box input {
+        width: 130px;
+        margin-right: 10px;
+    }
+
+    .assobox .candidate select {
+        height: 166px;
+        overflow: auto;
+    }
+    #vlan_interface {
+        background-color: #1b2d43 !important;
+        color: #ccc !important;
+        border: none;
+        border-radius: 6px;
+        background-clip: padding-box;
+        margin-right: 6px;
+    }
+    .assobox .form-group {
+        align-items: flex-start;
+    }
+    .tunnel_name_ctlgrp, .vlan_name_ctlgrp {
+        position: relative;
+    }
+    .content {
+        position: relative;
+    }
+    .btn-static {
+        position: absolute;
+        top: 0;
+        right: 0;
+        z-index: 10;
+        display: flex;
+        justify-content: flex-end;
+    }
+    .fixed-vlan-warning {
+        position: fixed;
+        padding: 14px;
+        top: 60px;
+        left: 50%;
+        transform: translateX(-50%);
+        z-index: 2000;
+        width: 600px;
+        max-width: 90vw;
+        margin: 0 auto;
+        box-shadow: 0 2px 8px rgba(0,0,0,0.15);
+    }
+    .fixed-vlan-warning .el-alert__closebtn {
+        top: 17px;
+    }
+</style>
+{% endblock %}
\ No newline at end of file
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/network/interface/geneve_interface/list.html
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/network/interface/geneve_interface/list.html	(revision 0)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/templates/network/interface/geneve_interface/list.html	(working copy)
@@ -0,0 +1,1030 @@
+{% extends "page_model.html" %}
+{% block list_active %}class="active"{% endblock %}
+{% block frame_name %}frame_model_list{% endblock %}
+
+{% block frame_model_main %}
+<div class="geneve_container" id="app">
+    <ul class="config-nav nav nav-pills">
+        <li :class="{ active: panel_active === 0 }">
+            <a class="config-nav-a" @click="changePanel(0)">{% trans %}Basic Settings{% endtrans %} <i class="fa fa-wrench"></i></a>
+        </li>
+        <li :class="{ active: panel_active === 1 }">
+            <a class="config-nav-a" @click="changePanel(1)">{% trans %}Configuration{% endtrans %} <i class="fa fa-wrench"></i></a>
+        </li>
+    </ul>
+    <div class="geneve-main">
+        <div
+            v-show="panel_active === 0"
+            class="content"
+        >
+            <div class="btn-static" v-show="showSaveBar">
+                <div class="btn-switch">
+                    <button type="button" class="btn btn-action" @click="saveGeneveBasicSetting">Save Changes</button>
+                    <button type="button" class="btn btn-default btn-cancel" @click="resetGeneveBasicSetting">Cancel</button>
+                </div>
+            </div>
+            <div class="settings-btn-box">
+                <label style="display: flex; align-items: center; gap: 8px;">
+                    <span class="col-md-3">Enable</span>
+                    <div class="switch">
+                        <input type="checkbox" v-model="enable_status" id="enable_switch">
+                        <span class="slider"></span>
+                    </div>
+                </label>
+                <label style="display: flex; align-items: center; gap: 8px;">
+                    <span class="col-md-3">Learning</span>
+                    <div class="switch">
+                        <input type="checkbox" v-model="learning_status" id="enable_switch">
+                        <span class="slider"></span>
+                    </div>
+                </label>
+                <fieldset>
+                    <div class="form-group">
+                        <label class="col-md-3">{% trans %}Port{% endtrans %}</label>
+                        <div>
+                            <input v-model="port" class="port_number" type="number" name="port_number" min="0" max="65535" /> (0-65535)
+                        </div>
+                    </div>
+                </fieldset>
+            </div>
+
+            <div class="interface-settings datatable table-box">
+                <div class="box-title">
+                    Interface Settings
+                </div>
+                <div class="box-header">
+                    <div class="box-bg-spe">
+                        <div class="box-icon-title">
+                            <i class="fa fa-list-alt"></i>
+                        </div>
+                    </div>
+                    <div class="control-group table-btn-group">
+                        <button @click="new_geneve_interface_show = true" type="button" class="btn btn-action add-btn"><i class="fa fa-plus-circle"></i>ADD</button>
+                        <button @click="deleteGeneveInterface()" type="button" class="btn btn-action delete-btn" :class="{ disabled: interfaceSettingDeleteStatus }"><i class="fa fa-minus-circle"></i>DELETE</button>
+                        <button @click="clearGeneveInterface()" type="button" class="btn btn-action clear-btn">Clear</button>
+                    </div>
+                    <div class="pull-right filter-control-group">
+                    </div>
+                </div>
+                <table id="geneve_table" class="display" style="width:100%">
+                    <thead>
+                        <tr>
+                            <th>ID</th>
+                            <th>{% trans %}Interface Name{% endtrans %}</th>
+                            <th>{% trans %}VNI{% endtrans %}</th>
+                        </tr>
+                    </thead>
+                </table>
+            </div>
+
+            <div class="interface-settings datatable table-box">
+                <div class="box-title">
+                    Tunnel Settings
+                </div>
+                <div class="box-header">
+                    <div class="box-bg-spe">
+                        <div class="box-icon-title">
+                            <i class="fa fa-list-alt"></i>
+                        </div>
+                    </div>
+                    <div class="control-group table-btn-group">
+                        <button @click="new_geneve_tunnel_show = true" type="button" class="btn btn-action add-btn"><i class="fa fa-plus-circle"></i>ADD</button>
+                        <button @click="deleteGeneveTunnel()" type="button" class="btn btn-action delete-btn" :class="{ disabled: tunnelSettingDeleteStatus }"><i class="fa fa-minus-circle"></i>DELETE</button>
+                        <button @click="clearGeneveTunnel()" type="button" class="btn btn-action clear-btn">Clear</button>
+                    </div>
+                    <div class="pull-right filter-control-group">
+                    </div>
+                </div>
+                <table id="geneve_tunnel_table" class="display" style="width:100%">
+                    <thead>
+                        <tr>
+                            <th>ID</th>
+                            <th>{% trans %}Tunnel Name{% endtrans %}</th>
+                            <th>{% trans %}Local IP{% endtrans %}</th>
+                            <th>{% trans %}Remote IP{% endtrans %}</th>
+                        </tr>
+                    </thead>
+                </table>
+            </div>
+        </div>
+        <div
+            v-show="panel_active === 1"
+            class="content"
+        >
+            <div class="action_drop">
+                <div class="dropdown" style="display:inline-block;">
+                    <button class="btn btn-action dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                        ACTIONS <span class="caret"></span>
+                    </button>
+                    <ul class="dropdown-menu dropdown-menu-right">
+                        <li>
+                            <a href="#" @click.prevent="clearGeneveConfiguration()">Clear</a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+            <form class="form-horizontal main-form" id="log-form">
+                <div class="row-fluid">
+                    <div class="span12 with-min-width field-group-box">
+                        <fieldset>
+                            <ul class="nav nav-pills pull-right">
+                                <li><a href="#" class="copy-btn" title="{% trans %}Copy to clipboard{% endtrans %}" data-clipboard-action="copy" data-clipboard-target="#geneve_con_pre" id="geneve_con_flash_copy" ><i class="fa fa-copy"></i></a></li>
+                                <li><a href="/apv/network/geneve/download" target="_blank" class="download-btn" title="{% trans %}Download as .txt file{% endtrans %}"><i class="fa fa-download"></i></a></li>
+                            </ul>
+                            <pre id="geneve_con_pre" >{[ geneve_con_text ]}</pre>
+                        </fieldset>
+                    </div>
+                </div>
+            </form>
+        </div>
+        <transition name="fade">
+            <div
+                class="new_lightbox"
+                v-if="new_geneve_interface_show"
+                v-cloak
+            >
+                <div class="lightbox-close"
+                    @click="new_geneve_interface_show = false"
+                >
+                    <i class="fa modal-close-icon">×</i>
+                </div>
+                <div class="lightbox-container">
+                    <div class="lightbox-box">
+                        <div class="lightbox-header">
+                            <span class="lightbox-title">
+                                <div class="box-icon-title">
+                                    <i class="fa fa-plus-circle"></i>
+                                </div>
+                                <div>New GENEVE interface</div>
+                            </span>
+                        </div>
+                        <div class="lightbox-content">
+                            <fieldset>
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">Interface Name&nbsp;</label>
+                                    <div>
+                                        <input v-model="add_geneve_value.name" type="text" id="interface_name" placeholder="">
+                                    </div>
+                                    <div v-if="addGeneveNameError != ''" class="input-error col-md-offset-3" style="color:#ff6b6b;font-size:12px;margin-top:2px;">
+                                        {[ addGeneveNameError ]}
+                                    </div>
+                                </div>
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">VNI&nbsp;</label>
+                                    <div>
+                                        <input v-model="add_geneve_value.vni" type="text" id="vni" placeholder="">
+                                        (1 to 32768)
+                                    </div>
+                                    <div v-if="addGeneveVniError != ''" class="input-error col-md-offset-3" style="color:#ff6b6b;font-size:12px;margin-top:2px;">
+                                        {[ addGeneveVniError ]}
+                                    </div>
+                                </div>
+                            </fieldset>
+                            <div class="btn-box col-md-offset-3">
+                                <button @click="addGeneveInterface()" type="button" class="btn btn-action" :disabled="addGeneveNameError != '' || addGeneveVniError != '' || add_geneve_value.name == '' || add_geneve_value.vni == ''">Create the GENEVE interface</button>
+                                <button @click="new_geneve_interface_show = false" type="button" class="btn btn-default btn-cancel">Cancel</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </transition>
+        <transition name="fade">
+            <div
+                class="new_lightbox"
+                v-if="new_geneve_tunnel_show"
+                v-cloak
+            >
+                <div class="lightbox-close"
+                    @click="new_geneve_tunnel_show = false"
+                >
+                    <i class="fa modal-close-icon">×</i>
+                </div>
+                <div class="lightbox-container">
+                    <div class="lightbox-box">
+                        <div class="lightbox-header">
+                            <span class="lightbox-title">
+                                <div class="box-icon-title">
+                                    <i class="fa fa-plus-circle"></i>
+                                </div>
+                                <div>New GENEVE Tunnel</div>
+                            </span>
+                        </div>
+                        <div class="lightbox-content">
+                            <fieldset>
+                                <div class="form-group textinput style-default">
+                                    <label class="col-md-3 control-label">Tunnel Name&nbsp;*</label>
+                                    <div>
+                                        <input type="text" v-model="tunnelForm.name" placeholder="">
+                                    </div>
+                                </div>
+                                <div class="form-group textinput style-default unionwidget">
+                                    <label class="col-md-3 control-label">Local IP&nbsp;*</label>
+                                    <div class="btn-group select-tab-group">
+                                        <label class="btn nested-radio" :class="{active: tunnelForm.local_ip_type === 'ipv4'}">
+                                            <input style="display:none;" type="radio" value="ipv4" v-model="tunnelForm.local_ip_type" />
+                                            <span class="field-name">IPv4</span>
+                                        </label>
+                                        <label class="btn nested-radio" :class="{active: tunnelForm.local_ip_type === 'ipv6'}">
+                                            <input style="display:none;" type="radio" value="ipv6" v-model="tunnelForm.local_ip_type" />
+                                            <span class="field-name">IPv6</span>
+                                        </label>
+                                    </div>
+                                    <div class="col-md-offset-3">
+                                        <input type="text" v-model="tunnelForm.local_ip" placeholder="">
+                                    </div>
+                                </div>
+                                <div class="form-group textinput style-default unionwidget">
+                                    <label class="col-md-3 control-label">Remote IP&nbsp;*</label>
+                                    <div class="btn-group select-tab-group">
+                                        <label class="btn nested-radio" :class="{active: tunnelForm.remote_ip_type === 'ipv4'}">
+                                            <input style="display:none;" type="radio" value="ipv4" v-model="tunnelForm.remote_ip_type" />
+                                            <span class="field-name">IPv4</span>
+                                        </label>
+                                        <label class="btn nested-radio" :class="{active: tunnelForm.remote_ip_type === 'ipv6'}">
+                                            <input style="display:none;" type="radio" value="ipv6" v-model="tunnelForm.remote_ip_type" />
+                                            <span class="field-name">IPv6</span>
+                                        </label>
+                                    </div>
+                                    <div class="col-md-offset-3">
+                                        <input type="text" v-model="tunnelForm.remote_ip" placeholder="">
+                                    </div>
+                                </div>
+                            </fieldset>
+                            <div class="btn-box col-md-offset-3">
+                                <button type="button" class="btn btn-action" @click="addGeneveTunnel()">Create the GENEVE Tunnel</button>
+                                <button @click="new_geneve_tunnel_show = false" type="button" class="btn btn-default btn-cancel">Cancel</button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </transition>
+    </div>
+</div>
+
+<script type="text/javascript">
+require(['clipboard', 'vue', 'list-list'], function(ClipboardJS, Vue){
+    var clipboard = new ClipboardJS('#geneve_con_flash_copy');
+    clipboard.on('error', function (e) {
+        console.log(e);
+    });
+
+    var v = new Vue({
+        delimiters: ['{[', ']}'],
+        el: "#app",
+        data: function() {
+            return {
+                geneve_con_text: '',
+                panel_active: 0,
+                selectedTokens: [],
+                selectedTunnelTokens: [],
+                interfaceSettingDeleteStatus: true,
+                tunnelSettingDeleteStatus: true,
+                enable_status: true,
+                learning_status: true,
+                port: 6018,
+                new_geneve_interface_show: false,
+                new_geneve_tunnel_show: false,
+                showSaveBar: false,
+                add_geneve_value: {
+                    name: '',
+                    vni: ''
+                },
+                addGeneveNameError: '',
+                addGeneveVniError: '',
+                originalGeneveSetting: {
+                    enable_status: true,
+                    learning_status: true,
+                    port: 6018
+                },
+                tunnelForm: {
+                    name: '',
+                    local_ip_type: 'ipv4',
+                    remote_ip_type: 'ipv4',
+                    local_ip: '',
+                    remote_ip: ''
+                }
+            };
+        },
+        watch: {
+            enable_status(val) {
+                this.checkGeneveBasicChanged();
+            },
+            learning_status(val) {
+                this.checkGeneveBasicChanged();
+            },
+            port(val) {
+                this.checkGeneveBasicChanged();
+            },
+            'tunnelForm.local_ip_type': function(newVal, oldVal) {
+                this.tunnelForm.local_ip = '';
+            },
+            'tunnelForm.remote_ip_type': function(newVal, oldVal) {
+                this.tunnelForm.remote_ip = '';
+            },
+            'add_geneve_value.name': function(val) {
+                if (!val) {
+                    this.addGeneveNameError = '';
+                } else if (val.length > 32) {
+                    this.addGeneveNameError = 'Name must not exceed 32 characters';
+                } else {
+                    this.addGeneveNameError = '';
+                }
+            },
+            'add_geneve_value.vni': function(val) {
+                if (!val) {
+                    this.addGeneveVniError = '';
+                } else if (!/^\d+$/.test(val)) {
+                    this.addGeneveVniError = 'VNI must be a number';
+                } else if (parseInt(val) < 1 || parseInt(val) > 32768) {
+                    this.addGeneveVniError = 'VNI must be between 1 and 32768';
+                } else {
+                    this.addGeneveVniError = '';
+                }
+            }
+        },
+        mounted: function () {
+            var self = this;
+            self.initDataTable();
+            self.getGeneveInterface();
+            self.getGeneveTunnelList();
+            this.$watch('panel_active', function(val) {
+                self.redrawAllDataTables();
+            });
+            self.getGeneveBasicSetting();
+            self.getGeneveConfiguration();
+        },
+        methods: {
+            changePanel: function(panel) {
+                this.panel_active = panel;
+            },
+            initDataTable: function() {
+                if ($.fn.DataTable.isDataTable('#geneve_table')) {
+                    $('#geneve_table').DataTable().destroy();
+                }
+                if ($.fn.DataTable.isDataTable('#geneve_tunnel_table')) {
+                    $('#geneve_tunnel_table').DataTable().destroy();
+                }
+            },
+            populateGeneveTable: function(data) {
+                var self = this;
+                $('#geneve_table').DataTable({
+                    data: data,
+                    columns: [
+                        {
+                            title: "<input type='checkbox' id='select-all' />",
+                            data: null,
+                            width: "40px",
+                            className: "dt-checkbox-col",
+                            render: function(data, type, row) {
+                                return `<input type='checkbox' class='select-checkbox' value='${row.name}' />`;
+                            },
+                            orderable: false
+                        },
+                        {
+                            title: "Interface Name",
+                            data: "name",
+                            render: function(data, type, row) {
+                                console.log(row)
+                                return `<a href="/apv/get_geneve_page?title=${row.name}&vni=${row.vni}&vlan=${row.vlan}">${data}</a>`;
+                            }
+                        },
+                        { title: "VNI", data: "vni" }
+                    ],
+                    columnDefs: [
+                        { width: "40px", targets: 0 }
+                    ],
+                    destroy: true,
+                    scrollX: true
+                });
+                // select all toggle
+                $('#select-all').on('click', function() {
+                    var rows = $('#geneve_table').DataTable().rows({ 'search': 'applied' }).nodes();
+                    $('input[type="checkbox"]', rows).prop('checked', this.checked);
+                    self.updateSelectedTokens();
+                });
+
+                // select simple
+                $('#geneve_table tbody').on('change', 'input[type="checkbox"]', function() {
+                    if (!this.checked) {
+                        var el = $('#select-all').get(0);
+                        if (el && el.checked && ('indeterminate' in el)) {
+                            el.indeterminate = true;
+                        }
+                    }
+                    self.updateSelectedTokens();
+                });
+            },
+            populateGeneveTunnelTable: function(data) {
+                var self = this;
+                $('#geneve_tunnel_table').DataTable({
+                    data: data,
+                    columns: [
+                        {
+                            title: "<input type='checkbox' id='select-all-tunnel' />",
+                            data: null,
+                            width: "40px",
+                            className: "dt-checkbox-col",
+                            render: function(data, type, row) {
+                                return `<input type='checkbox' class='select-checkbox' value='${row.name}' />`;
+                            },
+                            orderable: false
+                        },
+                        { title: "Tunnel Name", data: "name" },
+                        { title: "Local IP", data: "local_ip" },
+                        { title: "Remote IP", data: "remote_ip" }
+                    ],
+                    columnDefs: [
+                        { width: "40px", targets: 0 }
+                    ],
+                    destroy: true,
+                    scrollX: true
+                });
+                // select all toggle
+                $('#select-all-tunnel').on('click', function() {
+                    var rows = $('#geneve_tunnel_table').DataTable().rows({ 'search': 'applied' }).nodes();
+                    $('input[type="checkbox"]', rows).prop('checked', this.checked);
+                    self.updateTunnelSelectedTokens();
+                });
+
+                // select simple
+                $('#geneve_tunnel_table tbody').on('change', 'input[type="checkbox"]', function() {
+                    if (!this.checked) {
+                        var el = $('#select-all-tunnel').get(0);
+                        if (el && el.checked && ('indeterminate' in el)) {
+                            el.indeterminate = true;
+                        }
+                    }
+                    self.updateTunnelSelectedTokens();
+                });
+            },
+            updateSelectedTokens: function() {
+                let selectedTokensTemp = [];
+                $('#geneve_table tbody input[type="checkbox"]:checked').each(function() {
+                    selectedTokensTemp.push($(this).val());
+                });
+                this.selectedTokens = selectedTokensTemp;
+
+                selectedTokensTemp.length > 0
+                    ? this.interfaceSettingDeleteStatus = false
+                    : this.interfaceSettingDeleteStatus = true;
+            },
+            updateTunnelSelectedTokens: function() {
+                let selectedTokensTemp = [];
+                $('#geneve_tunnel_table tbody input[type="checkbox"]:checked').each(function() {
+                    selectedTokensTemp.push($(this).val());
+                });
+                this.selectedTunnelTokens = selectedTokensTemp;
+
+                selectedTokensTemp.length > 0
+                    ? this.tunnelSettingDeleteStatus = false
+                    : this.tunnelSettingDeleteStatus = true;
+            },
+            redrawAllDataTables: function() {
+                if ($.fn.DataTable.isDataTable('#geneve_table')) {
+                    $('#geneve_table').DataTable().columns.adjust().draw(false);
+                }
+                if ($.fn.DataTable.isDataTable('#geneve_tunnel_table')) {
+                    $('#geneve_tunnel_table').DataTable().columns.adjust().draw(false);
+                }
+            },
+            getGeneveBasicSetting: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/BasicSetting/_field_group?name=get',
+                    type: 'GET',
+                    cache: false,
+                    dataType: 'json'
+                }).then(function(data){
+                    self.enable_status = data.enable;
+                    self.learning_status = data.learning;
+                    self.port = data.port;
+                    self.originalGeneveSetting = {
+                        enable_status: data.enable,
+                        learning_status: data.learning,
+                        port: data.port
+                    };
+                    self.showSaveBar = false;
+                });
+            },
+            checkGeneveBasicChanged: function() {
+                this.showSaveBar =
+                    this.enable_status !== this.originalGeneveSetting.enable_status ||
+                    this.learning_status !== this.originalGeneveSetting.learning_status ||
+                    this.port !== this.originalGeneveSetting.port;
+            },
+            resetGeneveBasicSetting: function() {
+                this.enable_status = this.originalGeneveSetting.enable_status;
+                this.learning_status = this.originalGeneveSetting.learning_status;
+                this.port = this.originalGeneveSetting.port;
+                this.showSaveBar = false;
+            },
+            saveGeneveBasicSetting: function() {
+                var self = this;
+                var post_data = JSON.stringify({
+                    enable: self.enable_status,
+                    learning: self.learning_status,
+                    port: self.port
+                });
+                $.ajax({
+                    url: '/api/apv/network/geneve/BasicSetting/_update',
+                    type: 'POST',
+                    data: {
+                        post_data: post_data
+                    },
+                    contentType: 'application/x-www-form-urlencoded',
+                    dataType: 'json'
+                }).then(function(resp){
+                    window.location.reload();
+                });
+            },
+            getGeneveConfiguration: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/Configuration/_field_group?name=get',
+                    type: 'GET',
+                    cache: false,
+                    dataType: 'json'
+                }).then(function(data){
+                    self.geneve_con_text = data.content;
+                });
+            },
+            clearGeneveConfiguration: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/Configuration/_perform',
+                    type: 'POST',
+                    data: {
+                        action: 'Clear',
+                        options: '{}'
+                    },
+                    contentType: 'application/x-www-form-urlencoded',
+                    dataType: 'json'
+                }).then(function(data){
+                    window.location.reload();
+                });
+            },
+            addGeneveInterface: function() {
+                var self = this;
+                var post_data = JSON.stringify({
+                    name: self.add_geneve_value.name,
+                    vni: self.add_geneve_value.vni,
+                });
+                $.ajax({
+                    url: '/api/apv/network/geneve/Interface/_add',
+                    type: 'POST',
+                    data: {
+                        post_data: post_data
+                    },
+                    contentType: 'application/x-www-form-urlencoded',
+                    dataType: 'json'
+                }).then(function(res){
+                    window.location.reload();
+                });
+            },
+            getGeneveInterface: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/Interface/_config_table',
+                    type: 'POST',
+                    dataType: 'json',
+                    data: {
+                        draw:1,
+                        columns: [
+                            {
+                                data:"name",
+                                name:"name",
+                                searchable:true,
+                                orderable:false,
+                                search: {
+                                    value: "",
+                                    regex: false
+                                }
+                            },
+                            {
+                                data:"vni",
+                                name:"vni",
+                                searchable:true,
+                                orderable:true,
+                                search: {
+                                    value: "",
+                                    regex: false
+                                }
+                            },
+                            {
+                                data:"vlan",
+                                name:"vlan",
+                                searchable:true,
+                                orderable:true,
+                                search: {
+                                    value: "",
+                                    regex: false
+                                }
+                            }
+                        ],
+                        start:0,
+                        length:100,
+                        search: {
+                            value: "",
+                            regex: false
+                        }
+                    },
+                }).then(function(data){
+                    self.populateGeneveTable(data.data);
+                });
+            },
+            deleteGeneveInterface: function() {
+                var self = this;
+                if (!self.selectedTokens || self.selectedTokens.length === 0) {
+                    console.log('Please select at least one interface to delete.');
+                    return;
+                }
+                var pkArr = self.selectedTokens.map(function(item) {
+                    var name = typeof item === 'object' && item !== null ? item.name : item;
+                    return JSON.stringify({ name: name });
+                });
+                var pkStr = pkArr.join('ÿÿÿÿÿ');
+                $.ajax({
+                    url: '/api/apv/network/geneve/Interface/_delete',
+                    type: 'POST',
+                    data: {
+                        pk: pkStr
+                    },
+                    contentType: 'application/x-www-form-urlencoded',
+                    dataType: 'json'
+                }).then(function(res){
+                    console.log(res)
+                    window.location.reload();
+                });
+            },
+            clearGeneveInterface: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/Interface/_perform',
+                    type: 'POST',
+                    dataType: "json",
+                    data: {
+                        action: 'Clear',
+                        options: '{}'
+                    },
+                    success: function(res) {
+                        console.log(res);
+                        window.location.reload();
+                    }
+                })
+            },
+            addGeneveTunnel: function() {
+                var self = this;
+                var post_data = JSON.stringify({
+                    name: self.tunnelForm.name,
+                    local_ip: self.tunnelForm.local_ip,
+                    remote_ip: self.tunnelForm.remote_ip
+                });
+                $.ajax({
+                    url: '/api/apv/network/geneve/Tunnel/_add',
+                    type: 'POST',
+                    dataType: "json",
+                    data: {
+                        post_data: post_data
+                    },
+                    success: function(res) {
+                        console.log(res);
+                        window.location.reload();
+                    }
+                });
+            },
+            deleteGeneveTunnel: function() {
+                var self = this;
+                if (!self.selectedTunnelTokens || self.selectedTunnelTokens.length === 0) {
+                    console.log('Please select at least one tunnel to delete.');
+                    return;
+                }
+                var pkArr = self.selectedTunnelTokens.map(function(item) {
+                    var name = typeof item === 'object' && item !== null ? item.name : item;
+                    return JSON.stringify({ name: name });
+                });
+                var pkStr = pkArr.join('ÿÿÿÿÿ');
+                fetch('/api/apv/network/geneve/Tunnel/_delete', {
+                    method: 'POST',
+                    headers: {
+                        'Content-Type': 'application/x-www-form-urlencoded'
+                    },
+                    body: 'pk=' + encodeURIComponent(pkStr)
+                })
+                .then(function(response) {
+                    if (!response.ok) throw new Error('Network response was not ok');
+                    return response.text();
+                })
+                .then(function(res) {
+                    console.log(res);
+                    if (res === 'None' || res === '' || res === null) {
+                        window.location.reload();
+                    }
+                })
+                .catch(function(err) {
+                    console.error('Delete tunnel failed:', err);
+                });
+            },
+            clearGeneveTunnel: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/Tunnel/_perform',
+                    type: 'POST',
+                    dataType: "json",
+                    data: {
+                        action: 'Clear',
+                        options: '{}'
+                    },
+                    success: function(res) {
+                        console.log(res);
+                        window.location.reload();
+                    }
+                })
+            },
+            getGeneveTunnelList: function() {
+                var self = this;
+                $.ajax({
+                    url: '/api/apv/network/geneve/Tunnel/_config_table',
+                    type: 'POST',
+                    dataType: "json",
+                    data: {
+                        draw:1,
+                        columns: [
+                            {
+                                data:"name",
+                                name:"name",
+                                searchable:true,
+                                orderable:false,
+                                search: {
+                                    value: "",
+                                    regex: false
+                                }
+                            },
+                            {
+                                data:"local_ip",
+                                name:"local_ip",
+                                searchable:true,
+                                orderable:true,
+                                search: {
+                                    value: "",
+                                    regex: false
+                                }
+                            },
+                            {
+                                data:"remote_ip",
+                                name:"remote_ip",
+                                searchable:true,
+                                orderable:true,
+                                search: {
+                                    value: "",
+                                    regex: false
+                                }
+                            }
+                        ],
+                        start:0,
+                        length:100,
+                        search: {
+                            value: "",
+                            regex: false
+                        }
+                    },
+                    success: function(res) {
+                        console.log(res);
+                        self.populateGeneveTunnelTable(res.data);
+                    }
+                });
+            },
+        }
+    });
+});
+</script>
+<style scoped>
+    .geneve-main {
+        background-color: #03072f;
+        padding: 20px;
+        color: #fff;
+    }
+    .config-nav li{
+        cursor: pointer;
+    }
+    #geneve_table {
+        width: 100%;
+        table-layout: fixed;
+    }
+    #geneve_table th, #geneve_table td {
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+    }
+    #geneve_table th.dt-checkbox-col, #geneve_table td.dt-checkbox-col {
+        width: 40px !important;
+        min-width: 40px !important;
+        max-width: 40px !important;
+    }
+    th.dt-checkbox-col, td.dt-checkbox-col {
+        text-align: left;
+    }
+    .dataTables_wrapper > .row {
+        margin-left: 0 !important;
+        margin-right: 0 !important;
+    }
+    .dataTables_wrapper .row {
+        align-items: center;
+        height: 40px;
+    }
+    .sorting, .sorting_asc, .sorting_desc {
+        cursor: pointer;
+    }
+    .table-btn-group {
+        margin-bottom: 10px;
+    }
+    .dataTables_wrapper .row {
+        display: flex;
+    }
+    .dataTables_wrapper .dataTables_filter {
+        top: -55px;
+    }
+    .field-group-box fieldset {
+        position: relative;
+    }
+    .main-form .pull-right.nav {
+        left: -10px;
+        top: -50px;
+    }
+    .table-box {
+        position: relative;
+        margin-top: 20px;
+        margin-bottom: 40px;
+    }
+    .box-title {
+        position: absolute;
+        background-color: #75adc9;
+        color: #fff;
+        right: 0;
+        top: -24px;
+        padding: 2px 40px;
+    }
+    .port_number {
+        height: 24px !important;
+        background-color: #1b2d43 !important;
+        color: #fff !important;
+        border: #1b2d43 !important;
+    }
+    .switch {
+        position: relative;
+        display: inline-block;
+        width: 49px;
+        height: 23px;
+    }
+    .switch input {
+        opacity: 0;
+        width: 0;
+        height: 0;
+    }
+    .slider {
+        position: absolute;
+        cursor: pointer;
+        top: 0; left: 0; right: 0; bottom: 0;
+        background-color: #ccc;
+        transition: 0.4s;
+        border-radius: 17px;
+    }
+    .slider:before {
+        position: absolute;
+        content: "";
+        height: 17px;
+        width: 17px;
+        left: 3px;
+        bottom: 3px;
+        background-color: white;
+        transition: 0.4s;
+        border-radius: 50%;
+    }
+    input:checked + .slider {
+        background-color: #2196F3;
+    }
+    input:checked + .slider:before {
+        transform: translateX(26px);
+    }
+    .settings-btn-box {
+        padding-top: 30px;
+        padding-left: 30%;
+        display: flex;
+        flex-direction: column;
+        gap: 8px;
+    }
+    thead {
+        color: #6a7a8c;
+    }
+    tbody>tr:nth-child(odd), .table>tbody>tr:nth-child(odd) {
+        background-color: #121633;
+    }
+
+    .new_lightbox {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: rgba(0, 0, 0, 0.5);
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        z-index: 1000;
+    }
+    .lightbox-close {
+        position: fixed;
+        z-index: 1;
+        top: 0;
+        right: 15px;
+        font-size: 40px;
+        padding: 5px;
+        cursor: pointer;
+        color: #fff;
+    }
+    .lightbox-box {
+        width: 800px;
+        margin: 0 auto;
+    }
+    .lightbox-title {
+        display: flex;
+        align-items: center;
+        gap: 10px;
+        font-size: 14px;
+    }
+    .lightbox-header {
+        display: flex;
+        align-items: center;
+        height: 36px;
+        border-radius: 6px 6px 0 0;
+        color: #fff;
+        background: #1b2d43;
+        padding: 0 20px;
+    }
+    .lightbox-content {
+        background-color: #03072f;
+        padding: 55px 60px 30px;
+    }
+    .lightbox-content fieldset {
+        display: flex;
+        flex-direction: column;
+        gap: 8px;
+    }
+    .lightbox-content fieldset input {
+        background-color: #1b2d43;
+        color: #ccc;
+        border: none;
+        border-radius: 6px;
+        background-clip: padding-box;
+        margin-right: 6px;
+    }
+    .btn-box {
+        margin-top: 30px;
+    }
+
+    .fade-enter-active, .fade-leave-active {
+        transition: opacity 0.3s;
+    }
+    .fade-enter, .fade-leave-to {
+        opacity: 0;
+    }
+    [v-cloak] {
+        display: none !important;
+    }
+    .content {
+        position: relative;
+    }
+    .btn-static {
+        position: absolute;
+        top: 0;
+        right: 0;
+        z-index: 10;
+        display: flex;
+        justify-content: flex-end;
+    }
+    .btn-switch {
+        display: flex;
+        gap: 8px;
+    }
+    .action_drop {
+        position: absolute;
+        top: 0;
+        right: 10px;
+        z-index: 20;
+        cursor: pointer;
+    }
+    .action_drop button {
+        background-color: transparent;
+        border: none;
+        box-shadow: none;
+    }
+    .action_drop button:hover,
+    .action_drop button:focus,
+    .action_drop button:active {
+        background-color: transparent !important;
+        border: none !important;
+        box-shadow: none !important;
+    }
+</style>
+{% endblock %}
\ No newline at end of file
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/tree.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/tree.py	(revision 39323)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/tree.py	(working copy)
@@ -222,6 +222,7 @@
     ('network', {'cls':MenuNode, 'verbose_name':_('Network'), 'icon':'fa-cloud', 'sub_nodes':D([
         ('interface', {'cls':MenuNode, 'verbose_name':_('Interface Settings'),'sub_nodes':D([
             ('sys_interface', {'cls':ModelNode, 'model':'network.interface.SystemInterface'}),
+            ('geneve_interface', {'cls':ModelNode, 'model':'network.geneve.Interface'}),
             ('bond_interface', {'cls':ModelNode, 'model':'network.interface.BondInterface'}),
             ('vlan_interface', {'cls':ModelNode, 'model':'network.interface.VlanInterface'}),
             ('vxlan_interface', {'cls':ModelNode, 'model':'network.vxlan.VXLANSetting'}),
Index: /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/urls.py
===================================================================
--- /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/urls.py	(revision 39323)
+++ /branches/rel_apv_10_7/usr/click/webui/htdocs/new/src/apv/urls.py	(working copy)
@@ -60,4 +60,5 @@
     url(r'^%s/%s/get_top_chart_data$' % (PRODUCT_KEYWORD, C_PATH_GSLB), get_top_chart_data),
     url(r'^%s/%s/get_hits_chart_data$' % (PRODUCT_KEYWORD, C_PATH_GSLB), get_hits_chart_data),
     url(r'^%s/network/geneve/download' % PRODUCT_KEYWORD, geneve_log_download),
+    url(r'^%s/get_geneve_page$' % PRODUCT_KEYWORD, get_geneve_page),
 )
