@@ -29,11 +29,15 @@ const string LAG_PREFIX = "PortChannel";
2929extern set<string> g_portSet;
3030extern map<string, set<string>> g_vlanMap;
3131extern bool g_init;
32+ extern bool g_minigraphVlan;
3233
3334LinkSync::LinkSync (DBConnector *db) :
3435 m_portTableProducer(db, APP_PORT_TABLE_NAME),
36+ m_vlanTableProducer(db, APP_VLAN_TABLE_NAME),
37+ m_vlanMemberTableProducer(db, APP_VLAN_MEMBER_TABLE_NAME),
3538 m_lagTableProducer(db, APP_LAG_TABLE_NAME),
3639 m_portTableConsumer(db, APP_PORT_TABLE_NAME),
40+ m_vlanMemberTableConsumer(db, APP_VLAN_MEMBER_TABLE_NAME),
3741 m_lagTableConsumer(db, APP_LAG_TABLE_NAME)
3842{
3943 /* See the comments for g_portSet in portsyncd.cpp */
@@ -52,6 +56,22 @@ LinkSync::LinkSync(DBConnector *db) :
5256 }
5357 }
5458 }
59+
60+ vector<KeyOpFieldsValuesTuple> tuples;
61+ m_vlanMemberTableConsumer.getTableContent (tuples);
62+
63+ for (auto tuple : tuples)
64+ {
65+ vector<string> keys = tokenize (kfvKey (tuple), ' :' );
66+ string vlan = keys[0 ];
67+ string member = keys[1 ];
68+
69+ if (g_vlanMap.find (vlan) == g_vlanMap.end ())
70+ {
71+ g_vlanMap[vlan] = set<string>();
72+ }
73+ g_vlanMap[vlan].insert (member);
74+ }
5575}
5676
5777void LinkSync::onMsg (int nlmsg_type, struct nl_object *obj)
@@ -65,14 +85,17 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj)
6585 string key = rtnl_link_get_name (link);
6686
6787 if (key.compare (0 , INTFS_PREFIX.length (), INTFS_PREFIX) &&
88+ key.compare (0 , VLAN_PREFIX.length (), VLAN_PREFIX) &&
6889 key.compare (0 , LAG_PREFIX.length (), LAG_PREFIX))
6990 {
7091 return ;
7192 }
7293
73- if (key.compare (0 , VLAN_PREFIX.length (), VLAN_PREFIX) == 0 )
94+ if (!g_minigraphVlan && key.compare (0 , VLAN_PREFIX.length (), VLAN_PREFIX) == 0 )
7495 {
75- /* VLAN APP config doesn't rely on netlink */
96+ /*
97+ * VLAN APP config doesn't rely on netlink when VLAN not configured from minigraph
98+ */
7699 return ;
77100 }
78101
@@ -108,12 +131,65 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj)
108131 return ;
109132 }
110133
134+ /* VLAN member: A separate entry in VLAN_TABLE will be inserted */
135+ if (master)
136+ {
137+ string master_key = m_ifindexNameMap[master];
138+ /* Verify the master interface starts with "Vlan" to exclude "PortChannel" interfaces */
139+ if (!master_key.compare (0 , VLAN_PREFIX.length (), VLAN_PREFIX))
140+ {
141+ string member_key = master_key + " :" + key;
142+
143+ if (nlmsg_type == RTM_DELLINK) /* Will it happen? */
144+ {
145+ m_vlanMemberTableProducer.del (member_key);
146+ }
147+ else /* RTM_NEWLINK */
148+ {
149+ vector<FieldValueTuple> fvVector;
150+ FieldValueTuple t (" tagging_mode" , " untagged" );
151+ fvVector.push_back (t);
152+
153+ m_vlanMemberTableProducer.set (member_key, fvVector);
154+ }
155+ }
156+ }
157+ /* No longer a VLAN member: Check if it was a member before and remove it */
158+ else
159+ {
160+ for (auto i = g_vlanMap.begin (); i != g_vlanMap.end (); i++)
161+ {
162+ set<string> member_set = (*i).second ;
163+ if (member_set.find (key) != member_set.end ())
164+ {
165+ string member_key = (*i).first + " :" + key;
166+ m_vlanMemberTableProducer.del (member_key);
167+ }
168+ }
169+ }
170+
111171 vector<FieldValueTuple> fvVector;
112172 FieldValueTuple a (" admin_status" , admin ? " up" : " down" );
113173 FieldValueTuple m (" mtu" , to_string (mtu));
114174 fvVector.push_back (a);
115175 fvVector.push_back (m);
116176
177+ /* VLAN interfaces: Check if the type is bridge */
178+ if (type && !strcmp (type, VLAN_DRV_NAME))
179+ {
180+ if (nlmsg_type == RTM_DELLINK)
181+ {
182+ m_vlanTableProducer.del (key);
183+ }
184+ else
185+ {
186+ FieldValueTuple o (" oper_status" , oper ? " up" : " down" );
187+ fvVector.push_back (o);
188+ m_vlanTableProducer.set (key, fvVector);
189+ }
190+ return ;
191+ }
192+
117193 /* front panel interfaces: Check if the port is in the PORT_TABLE
118194 * non-front panel interfaces such as eth0, lo which are not in the
119195 * PORT_TABLE are ignored. */
0 commit comments