diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp
index aa6354ecc778..e6073389f970 100644
--- a/portsyncd/linksync.cpp
+++ b/portsyncd/linksync.cpp
@@ -12,10 +12,17 @@
 #include "portsyncd/linksync.h"
 
 #include <iostream>
+#include <set>
 
 using namespace std;
 using namespace swss;
 
+#define VLAN_DRV_NAME   "bridge"
+#define TEAM_DRV_NAME   "team"
+
+extern set<string> g_portSet;
+extern bool g_init;
+
 LinkSync::LinkSync(DBConnector *db) :
     m_portTableProducer(db, APP_PORT_TABLE_NAME),
     m_vlanTableProducer(db, APP_VLAN_TABLE_NAME),
@@ -24,24 +31,79 @@ LinkSync::LinkSync(DBConnector *db) :
     m_vlanTableConsumer(db, APP_VLAN_TABLE_NAME),
     m_lagTableConsumer(db, APP_LAG_TABLE_NAME)
 {
+    /* See the comments for g_portSet in linksync.h */
+    for (string port : g_portSet)
+    {
+        vector<FieldValueTuple> temp;
+        if (m_portTableConsumer.get(port, temp))
+        {
+            for (auto it : temp)
+            {
+                if (fvField(it) == "admin_status")
+                {
+                    g_portSet.erase(port);
+                    break;
+                }
+            }
+        }
+    }
 }
 
 void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj)
 {
-    if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_GETLINK) &&
-        (nlmsg_type != RTM_DELLINK))
+    if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_DELLINK))
         return;
 
     struct rtnl_link *link = (struct rtnl_link *)obj;
     string key = rtnl_link_get_name(link);
-    if (nlmsg_type == RTM_DELLINK) /* Will be sync by other application */
+
+    if (key == "lo" || key == "eth0" || key == "docker0" || key == "bcm0")
         return;
 
-    bool admin_state = rtnl_link_get_flags(link) & IFF_UP;
-    bool oper_state = rtnl_link_get_flags(link) & IFF_LOWER_UP;
+    unsigned int flags = rtnl_link_get_flags(link);
+    bool admin_state = flags & IFF_UP;
+    bool oper_state = flags & IFF_LOWER_UP;
     unsigned int mtu = rtnl_link_get_mtu(link);
 
+    char addrStr[MAX_ADDR_SIZE+1] = {0};
+    nl_addr2str(rtnl_link_get_addr(link), addrStr, MAX_ADDR_SIZE);
+
+    unsigned int ifindex = rtnl_link_get_ifindex(link);
+    int master = rtnl_link_get_master(link);
+    char *type = rtnl_link_get_type(link);
+
+    cout << "Receive nlmsg from portsyncd: type:" << nlmsg_type << " key:" << key
+         << " admin_state:" << admin_state << " oper_state:" << oper_state
+         << " addr:" << addrStr << " ifindex:" << ifindex << " master:" << master;
+    if (type)
+        cout << " type:" << type;
+    cout << endl;
+
+    /* Insert or update the ifindex to key map */
+    m_ifindexNameMap[ifindex] = key;
+
+    /* Will be dealt by teamsyncd */
+    if (type && !strcmp(type, TEAM_DRV_NAME))
+        return;
+
     vector<FieldValueTuple> fvVector;
+
+    /* VLAN member: A separate entry in VLAN_TABLE will be inserted */
+    if (master)
+    {
+        key = m_ifindexNameMap[master] + ":" + key;
+
+        if (nlmsg_type == RTM_DELLINK)
+            m_vlanTableProducer.del(key);
+        else
+        {
+            FieldValueTuple t("tagging_mode", "untagged");
+            fvVector.push_back(t);
+
+            m_vlanTableProducer.set(key, fvVector);
+        }
+    }
+
     FieldValueTuple a("admin_status", admin_state ? "up" : "down");
     FieldValueTuple o("oper_status", oper_state ? "up" : "down");
     FieldValueTuple m("mtu", to_string(mtu));
@@ -49,38 +111,36 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj)
     fvVector.push_back(o);
     fvVector.push_back(m);
 
+    /* VLAN interfaces: Check if the type is bridge */
+    if (type && !strcmp(type, VLAN_DRV_NAME))
+    {
+        if (nlmsg_type == RTM_DELLINK)
+            m_vlanTableProducer.del(key);
+        else
+            m_vlanTableProducer.set(key, fvVector);
+
+        return;
+    }
+
+    /* front panel interfaces: Check if the port is in the PORT_TABLE */
     vector<FieldValueTuple> temp;
-    if (m_lagTableConsumer.get(key, temp))
-        m_lagTableProducer.set(key, fvVector);
-    else if (m_vlanTableConsumer.get(key, temp))
-        m_vlanTableProducer.set(key, fvVector);
-    else if (m_portTableConsumer.get(key, temp))
+    if (m_portTableConsumer.get(key, temp))
     {
-        /*
-         * If the port entry is just initialized without having admin_status/oper_status field,
-         * we manually bring up the port using ifup --force command.
-         */
-        bool init = true;
-        for (auto it : temp)
-        {
-            if (fvField(it) == "admin_status")
-            {
-                init = false;
-                break;
-            }
-        }
+        /* TODO: When port is removed from the kernel */
+        if (nlmsg_type == RTM_DELLINK)
+            return;
 
-        /*
-         * TODO: Parse /etc/network/interfaces file to bring up port and configure corresponding IP.
-         */
-        if (init)
+        if (!g_init && g_portSet.find(key) != g_portSet.end())
         {
+            /* Bring up the front panel port as the first place*/
             system(("/sbin/ifup --force " + key).c_str());
+            g_portSet.erase(key);
         }
         else
-        {
             m_portTableProducer.set(key, fvVector);
-        }
+
+        return;
     }
-    /* else discard managment or untracked netdev state */
+
+    cerr << "Unhandled netlink message received." << endl;
 }
diff --git a/portsyncd/linksync.h b/portsyncd/linksync.h
index 1a22ab7de647..dcb183a0c736 100644
--- a/portsyncd/linksync.h
+++ b/portsyncd/linksync.h
@@ -5,6 +5,8 @@
 #include "producertable.h"
 #include "netmsg.h"
 
+#include <map>
+
 namespace swss {
 
 class LinkSync : public NetMsg
@@ -19,6 +21,8 @@ class LinkSync : public NetMsg
 private:
     ProducerTable m_portTableProducer, m_vlanTableProducer, m_lagTableProducer;
     Table m_portTableConsumer, m_vlanTableConsumer, m_lagTableConsumer;
+
+    std::map<unsigned int, std::string> m_ifindexNameMap;
 };
 
 }
diff --git a/portsyncd/portsyncd.cpp b/portsyncd/portsyncd.cpp
index ee851a70b602..9cfb703da756 100644
--- a/portsyncd/portsyncd.cpp
+++ b/portsyncd/portsyncd.cpp
@@ -14,33 +14,59 @@
 #include <set>
 #include <map>
 
-#define DEFAULT_PORT_CONFIG_FILE "port_config.ini"
+#define DEFAULT_PORT_CONFIG_FILE     "port_config.ini"
+#define DEFAULT_VLAN_INTERFACES_FILE "/etc/network/interfaces.d/vlan_interfaces"
 
 using namespace std;
 using namespace swss;
 
-void usage(char **argv)
+/*
+ * This m_portSet contains all the front panel ports that the corresponding
+ * host interfaces needed to be created. When this LinkSync class is
+ * initialized, we check the database to see if some of the ports' host
+ * interfaces are already created and remove them from this set. We will
+ * remove the rest of the ports in the set when receiving the first netlink
+ * message indicating that the host interfaces are created. After the set
+ * is empty, we send out the signal ConfigDone and bring up VLAN interfaces
+ * when the vlan_interfaces file exists. g_init is used to limit the command
+ * to be run only once.
+ */
+set<string> g_portSet;
+bool g_init = false;
+
+void usage()
 {
-    cout << "Usage: " << argv[0] << " [-f config_file]" << endl;
+    cout << "Usage: portsyncd [-p port_config.ini] [-v vlan_interfaces]" << endl;
+    cout << "       -p port_config.ini: MANDATORY import port lane mapping" << endl;
+    cout << "                           default: port_config.ini" << endl;
+    cout << "       -v vlan_interfaces: import VLAN interfaces configuration file" << endl;
+    cout << "                           default: /etc/network/interfaces.d/vlan_interfaces" << endl;
 }
 
+void handlePortConfigFile(ProducerTable &p, string file);
+void handleVlanIntfFile(string file);
+
 int main(int argc, char **argv)
 {
     int opt;
     string port_config_file = DEFAULT_PORT_CONFIG_FILE;
+    string vlan_interfaces_file = DEFAULT_VLAN_INTERFACES_FILE;
 
-    while ((opt = getopt(argc, argv, "f:h")) != -1 )
+    while ((opt = getopt(argc, argv, "p:v:h")) != -1 )
     {
         switch (opt)
         {
-        case 'f':
+        case 'p':
             port_config_file.assign(optarg);
             break;
+        case 'v':
+            vlan_interfaces_file.assign(optarg);
+            break;
         case 'h':
-            usage(argv);
+            usage();
             return 1;
         default: /* '?' */
-            usage(argv);
+            usage();
             return EXIT_FAILURE;
         }
     }
@@ -48,16 +74,76 @@ int main(int argc, char **argv)
     DBConnector db(0, "localhost", 6379, 0);
     ProducerTable p(&db, APP_PORT_TABLE_NAME);
 
-    ifstream infile(port_config_file);
-    if (!infile.is_open())
+    LinkSync sync(&db);
+    NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, &sync);
+    NetDispatcher::getInstance().registerMessageHandler(RTM_DELLINK, &sync);
+
+    try
+    {
+        NetLink netlink;
+        Select s;
+
+        netlink.registerGroup(RTNLGRP_LINK);
+        cout << "Listen to link messages..." << endl;
+        netlink.dumpRequest(RTM_GETLINK);
+
+        handlePortConfigFile(p, port_config_file);
+
+        s.addSelectable(&netlink);
+        while (true)
+        {
+            Selectable *temps;
+            int tempfd, ret;
+            ret = s.select(&temps, &tempfd, 1);
+
+            if (ret == Select::ERROR)
+            {
+                cerr << "Error had been returned in select" << endl;
+                continue;
+            }
+
+            if (ret == Select::TIMEOUT)
+            {
+                if (!g_init && g_portSet.empty())
+                {
+                    /*
+                     * After finishing reading port configuration file and
+                     * creating all host interfaces, this daemon shall send
+                     * out a signal to orchagent indicating port initialization
+                     * procedure is done and other application could start
+                     * syncing.
+                     */
+                    FieldValueTuple finish_notice("lanes", "0");
+                    vector<FieldValueTuple> attrs = { finish_notice };
+                    p.set("ConfigDone", attrs);
+
+                    handleVlanIntfFile(vlan_interfaces_file);
+
+                    g_init = true;
+                }
+            }
+        }
+    }
+    catch (...)
     {
-        cerr << "Port configuration file not found! " << port_config_file << endl;
-        usage(argv);
+        cerr << "Exception had been thrown in deamon" << endl;
         return EXIT_FAILURE;
     }
 
+    return 1;
+}
+
+void handlePortConfigFile(ProducerTable &p, string file)
+{
     cout << "Read port configuration file..." << endl;
 
+    ifstream infile(file);
+    if (!infile.is_open())
+    {
+        usage();
+        throw "Port configuration file not found!";
+    }
+
     string line;
     while (getline(infile, line))
     {
@@ -73,48 +159,22 @@ int main(int argc, char **argv)
         FieldValueTuple lanes_attr("lanes", lanes);
         vector<FieldValueTuple> attrs = { lanes_attr };
         p.set(alias, attrs);
+
+        g_portSet.insert(alias);
     }
 
     infile.close();
+}
 
-    /*
-     * After finishing reading port configuration file, this daemon shall send
-     * out a signal to orchagent indicating port initialization procedure is
-     * done and other application could start syncing.
-     */
-    FieldValueTuple finish_notice("lanes", "0");
-    vector<FieldValueTuple> attrs = { finish_notice };
-    p.set("ConfigDone", attrs);
-
-    LinkSync sync(&db);
-    NetDispatcher::getInstance().registerMessageHandler(RTM_NEWLINK, &sync);
-    NetDispatcher::getInstance().registerMessageHandler(RTM_DELLINK, &sync);
-
-    while (true)
+void handleVlanIntfFile(string file)
+{
+    ifstream infile(file);
+    if (infile.good())
     {
-        try
-        {
-            NetLink netlink;
-            Select s;
-
-            netlink.registerGroup(RTNLGRP_LINK);
-            cout << "Listen to link messages..." << endl;
-            netlink.dumpRequest(RTM_GETLINK);
-
-            s.addSelectable(&netlink);
-            while (true)
-            {
-                Selectable *temps;
-                int tempfd;
-                s.select(&temps, &tempfd);
-            }
-        }
-        catch (...)
-        {
-            cerr << "Exception had been thrown in deamon" << endl;
-            return EXIT_FAILURE;
-        }
+        /* Bring up VLAN interfaces when vlan_interfaces_file exists */
+        string cmd = "/sbin/ifup --all --force --interfaces " + file;
+        int ret = system(cmd.c_str());
+        if (!ret)
+            cerr << "Execute command returns non-zero value! " << cmd << endl;
     }
-
-    return 1;
 }